From eb0b894e1c98f47c5e3a6b7ad87b30f942f263c6 Mon Sep 17 00:00:00 2001 From: Andrea Pavone Date: Sun, 10 Nov 2024 19:06:42 +0100 Subject: [PATCH] Move components inside folders Signed-off-by: Andrea Pavone --- package-lock.json | 206 ++++++++++++++++++ package.json | 5 + .../{ => Dashboard}/DashboardHeader.tsx | 5 +- .../Dashboard/Leaks/LeaksEnumerationCard.tsx | 21 ++ .../Dashboard/Leaks/LeaksResolvedCard.tsx | 26 +++ .../Dashboard/Leaks/LeaksUnresolvedCard.tsx | 26 +++ .../Overview/OverviewCertificatesCard.tsx | 23 ++ .../Overview/OverviewDataLeaksCard.tsx | 26 +++ .../Overview/OverviewEmailSecurityCard.tsx | 31 +++ .../Overview/OverviewNetworkAssetsCard.tsx | 26 +++ .../Overview/OverviewSimilarDomainsCard.tsx | 21 ++ .../OverviewVulnerabilityScoreCard.tsx | 35 +++ .../Dashboard/Services/ServicesCdnCard.tsx | 30 +++ .../Services/ServicesPortExposureCard.tsx} | 6 +- .../Dashboard/Services/ServicesWafCard.tsx | 30 +++ .../VulnerabilitiesActiveCard.tsx | 90 ++++++++ .../VulnerabilitiesPassiveCard.tsx | 85 ++++++++ .../NumberOfVulnerabilitiesPieChart.tsx | 157 ------------- .../SecurityScoresOverviewBarChart.tsx | 5 +- .../js/Components/VulnerabilityPieChart.tsx | 78 +++++++ resources/js/Components/ui/calendar.tsx | 70 ++++++ resources/js/Components/ui/checkbox.tsx | 28 +++ resources/js/Components/ui/dropdown-menu.tsx | 199 +++++++++++++++++ resources/js/Components/ui/input.tsx | 22 ++ resources/js/Components/ui/table.tsx | 120 ++++++++++ resources/js/Pages/Dashboard.tsx | 192 ++++++++-------- resources/js/Pages/Home.tsx | 85 ++++++++ routes/web.php | 8 +- 28 files changed, 1383 insertions(+), 273 deletions(-) rename resources/js/Components/{ => Dashboard}/DashboardHeader.tsx (96%) create mode 100644 resources/js/Components/Dashboard/Leaks/LeaksEnumerationCard.tsx create mode 100644 resources/js/Components/Dashboard/Leaks/LeaksResolvedCard.tsx create mode 100644 resources/js/Components/Dashboard/Leaks/LeaksUnresolvedCard.tsx create mode 100644 resources/js/Components/Dashboard/Overview/OverviewCertificatesCard.tsx create mode 100644 resources/js/Components/Dashboard/Overview/OverviewDataLeaksCard.tsx create mode 100644 resources/js/Components/Dashboard/Overview/OverviewEmailSecurityCard.tsx create mode 100644 resources/js/Components/Dashboard/Overview/OverviewNetworkAssetsCard.tsx create mode 100644 resources/js/Components/Dashboard/Overview/OverviewSimilarDomainsCard.tsx create mode 100644 resources/js/Components/Dashboard/Overview/OverviewVulnerabilityScoreCard.tsx create mode 100644 resources/js/Components/Dashboard/Services/ServicesCdnCard.tsx rename resources/js/Components/{PortExposureAnalysis.tsx => Dashboard/Services/ServicesPortExposureCard.tsx} (94%) create mode 100644 resources/js/Components/Dashboard/Services/ServicesWafCard.tsx create mode 100644 resources/js/Components/Dashboard/Vulnerabilities/VulnerabilitiesActiveCard.tsx create mode 100644 resources/js/Components/Dashboard/Vulnerabilities/VulnerabilitiesPassiveCard.tsx delete mode 100644 resources/js/Components/NumberOfVulnerabilitiesPieChart.tsx create mode 100644 resources/js/Components/VulnerabilityPieChart.tsx create mode 100644 resources/js/Components/ui/calendar.tsx create mode 100644 resources/js/Components/ui/checkbox.tsx create mode 100644 resources/js/Components/ui/dropdown-menu.tsx create mode 100644 resources/js/Components/ui/input.tsx create mode 100644 resources/js/Components/ui/table.tsx create mode 100644 resources/js/Pages/Home.tsx diff --git a/package-lock.json b/package-lock.json index 6df9f4b..722333a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,13 +5,18 @@ "packages": { "": { "dependencies": { + "@radix-ui/react-checkbox": "^1.1.2", + "@radix-ui/react-dropdown-menu": "^2.1.2", "@radix-ui/react-progress": "^1.1.0", "@radix-ui/react-select": "^2.1.2", "@radix-ui/react-slot": "^1.1.0", "@radix-ui/react-tabs": "^1.1.1", + "@tanstack/react-table": "^8.20.5", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", + "date-fns": "^3.6.0", "lucide-react": "^0.456.0", + "react-day-picker": "^8.10.1", "react-markdown": "^9.0.1", "recharts": "^2.13.3", "tailwind-merge": "^2.5.4", @@ -985,6 +990,51 @@ } } }, + "node_modules/@radix-ui/react-checkbox": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-checkbox/-/react-checkbox-1.1.2.tgz", + "integrity": "sha512-/i0fl686zaJbDQLNKrkCbMyDm6FQMt4jg323k7HuqitoANm9sE23Ql8yOK3Wusk34HSLKDChhMux05FnP6KUkw==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.0", + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-context": "1.1.1", + "@radix-ui/react-presence": "1.1.1", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-use-controllable-state": "1.1.0", + "@radix-ui/react-use-previous": "1.1.0", + "@radix-ui/react-use-size": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/react-context": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.1.tgz", + "integrity": "sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-collection": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.0.tgz", @@ -1083,6 +1133,50 @@ } } }, + "node_modules/@radix-ui/react-dropdown-menu": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.1.2.tgz", + "integrity": "sha512-GVZMR+eqK8/Kes0a36Qrv+i20bAPXSn8rCBTHx30w+3ECnR5o3xixAlqcVaYvLeyKUsm0aqyhWfmUcqufM8nYA==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.0", + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-context": "1.1.1", + "@radix-ui/react-id": "1.1.0", + "@radix-ui/react-menu": "2.1.2", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-use-controllable-state": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dropdown-menu/node_modules/@radix-ui/react-context": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.1.tgz", + "integrity": "sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-focus-guards": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.1.tgz", @@ -1141,6 +1235,61 @@ } } }, + "node_modules/@radix-ui/react-menu": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.1.2.tgz", + "integrity": "sha512-lZ0R4qR2Al6fZ4yCCZzu/ReTFrylHFxIqy7OezIpWF4bL0o9biKo0pFIvkaew3TyZ9Fy5gYVrR5zCGZBVbO1zg==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.0", + "@radix-ui/react-collection": "1.1.0", + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-context": "1.1.1", + "@radix-ui/react-direction": "1.1.0", + "@radix-ui/react-dismissable-layer": "1.1.1", + "@radix-ui/react-focus-guards": "1.1.1", + "@radix-ui/react-focus-scope": "1.1.0", + "@radix-ui/react-id": "1.1.0", + "@radix-ui/react-popper": "1.2.0", + "@radix-ui/react-portal": "1.1.2", + "@radix-ui/react-presence": "1.1.1", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-roving-focus": "1.1.0", + "@radix-ui/react-slot": "1.1.0", + "@radix-ui/react-use-callback-ref": "1.1.0", + "aria-hidden": "^1.1.1", + "react-remove-scroll": "2.6.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-context": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.1.tgz", + "integrity": "sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-popper": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.0.tgz", @@ -1930,6 +2079,26 @@ "tailwindcss": ">=3.0.0 || >= 3.0.0-alpha.1 || >= 4.0.0-alpha.20" } }, + "node_modules/@tanstack/react-table": { + "version": "8.20.5", + "resolved": "https://registry.npmjs.org/@tanstack/react-table/-/react-table-8.20.5.tgz", + "integrity": "sha512-WEHopKw3znbUZ61s9i0+i9g8drmDo6asTWbrQh8Us63DAk/M0FkmIqERew6P71HI75ksZ2Pxyuf4vvKh9rAkiA==", + "license": "MIT", + "dependencies": { + "@tanstack/table-core": "8.20.5" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": ">=16.8", + "react-dom": ">=16.8" + } + }, "node_modules/@tanstack/react-virtual": { "version": "3.10.9", "resolved": "https://registry.npmjs.org/@tanstack/react-virtual/-/react-virtual-3.10.9.tgz", @@ -1948,6 +2117,19 @@ "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, + "node_modules/@tanstack/table-core": { + "version": "8.20.5", + "resolved": "https://registry.npmjs.org/@tanstack/table-core/-/table-core-8.20.5.tgz", + "integrity": "sha512-P9dF7XbibHph2PFRz8gfBKEXEY/HJPOhym8CHmjF8y3q5mWpKx9xtZapXQUWCgkqvsK0R46Azuz+VaxD4Xl+Tg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, "node_modules/@tanstack/virtual-core": { "version": "3.10.9", "resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.10.9.tgz", @@ -2916,6 +3098,16 @@ "node": ">=12" } }, + "node_modules/date-fns": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz", + "integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/kossnocorp" + } + }, "node_modules/debug": { "version": "4.3.7", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", @@ -4927,6 +5119,20 @@ "node": ">=0.10.0" } }, + "node_modules/react-day-picker": { + "version": "8.10.1", + "resolved": "https://registry.npmjs.org/react-day-picker/-/react-day-picker-8.10.1.tgz", + "integrity": "sha512-TMx7fNbhLk15eqcMt+7Z7S2KF7mfTId/XJDjKE8f+IUcFn0l08/kI4FiYTL/0yuOLmEcbR4Fwe3GJf/NiiMnPA==", + "license": "MIT", + "funding": { + "type": "individual", + "url": "https://github.com/sponsors/gpbl" + }, + "peerDependencies": { + "date-fns": "^2.28.0 || ^3.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/react-dom": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", diff --git a/package.json b/package.json index ab106e9..9dedad7 100644 --- a/package.json +++ b/package.json @@ -25,13 +25,18 @@ "vite": "^5.0" }, "dependencies": { + "@radix-ui/react-checkbox": "^1.1.2", + "@radix-ui/react-dropdown-menu": "^2.1.2", "@radix-ui/react-progress": "^1.1.0", "@radix-ui/react-select": "^2.1.2", "@radix-ui/react-slot": "^1.1.0", "@radix-ui/react-tabs": "^1.1.1", + "@tanstack/react-table": "^8.20.5", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", + "date-fns": "^3.6.0", "lucide-react": "^0.456.0", + "react-day-picker": "^8.10.1", "react-markdown": "^9.0.1", "recharts": "^2.13.3", "tailwind-merge": "^2.5.4", diff --git a/resources/js/Components/DashboardHeader.tsx b/resources/js/Components/Dashboard/DashboardHeader.tsx similarity index 96% rename from resources/js/Components/DashboardHeader.tsx rename to resources/js/Components/Dashboard/DashboardHeader.tsx index 05fd68b..168acee 100644 --- a/resources/js/Components/DashboardHeader.tsx +++ b/resources/js/Components/Dashboard/DashboardHeader.tsx @@ -2,15 +2,16 @@ import {SecuritySummaryReportResultType} from "@/types/security-summary"; import {Card, CardContent, CardHeader, CardTitle} from "@/Components/ui/card"; import {Check, Copy, ShieldAlert} from "lucide-react"; import {Button} from "@/Components/ui/button"; -import React from "react"; +import React, {useState} from "react"; import {useClipboard} from "use-clipboard-copy"; export default function DashboardHeader({ reportData }: { reportData: SecuritySummaryReportResultType }) { - const [isCopied, setIsCopied] = React.useState(false); + const [isCopied, setIsCopied] = useState(false); const clipboard = useClipboard(); + const handleCopy = () => { clipboard.copy(reportData.idsummary) setIsCopied(true) diff --git a/resources/js/Components/Dashboard/Leaks/LeaksEnumerationCard.tsx b/resources/js/Components/Dashboard/Leaks/LeaksEnumerationCard.tsx new file mode 100644 index 0000000..5a4e6b9 --- /dev/null +++ b/resources/js/Components/Dashboard/Leaks/LeaksEnumerationCard.tsx @@ -0,0 +1,21 @@ +import {SecuritySummaryReportResultType} from "@/types/security-summary"; +import {Card, CardContent, CardHeader, CardTitle} from "@/Components/ui/card"; +import {Database} from "lucide-react"; +import React from "react"; + +export default function LeaksEnumerationCard({ reportData }: { reportData: SecuritySummaryReportResultType }) { + return ( + + + + + Enumeration + + + +
{reportData.n_dataleak.enumeration}
+
+
+ ) +} diff --git a/resources/js/Components/Dashboard/Leaks/LeaksResolvedCard.tsx b/resources/js/Components/Dashboard/Leaks/LeaksResolvedCard.tsx new file mode 100644 index 0000000..18c7883 --- /dev/null +++ b/resources/js/Components/Dashboard/Leaks/LeaksResolvedCard.tsx @@ -0,0 +1,26 @@ +import {SecuritySummaryReportResultType} from "@/types/security-summary"; +import {Card, CardContent, CardDescription, CardHeader, CardTitle} from "@/Components/ui/card"; +import {Database} from "lucide-react"; +import React from "react"; + +export default function LeaksResolvedCard({ reportData }: { reportData: SecuritySummaryReportResultType }) { + return ( + + + + + Resolved + + Resolved data leak incidents + + +
{reportData.n_dataleak.resolved.potential_stealer}
+
+ Including {reportData.n_dataleak.resolved.domain_stealer} domain stealer + and {reportData.n_dataleak.resolved.other_stealer} other leaks +
+
+
+ ) +} diff --git a/resources/js/Components/Dashboard/Leaks/LeaksUnresolvedCard.tsx b/resources/js/Components/Dashboard/Leaks/LeaksUnresolvedCard.tsx new file mode 100644 index 0000000..ae68367 --- /dev/null +++ b/resources/js/Components/Dashboard/Leaks/LeaksUnresolvedCard.tsx @@ -0,0 +1,26 @@ +import {SecuritySummaryReportResultType} from "@/types/security-summary"; +import {Card, CardContent, CardDescription, CardHeader, CardTitle} from "@/Components/ui/card"; +import {Database} from "lucide-react"; +import React from "react"; + +export default function LeaksUnresolvedCard({ reportData }: { reportData: SecuritySummaryReportResultType }) { + return ( + + + + + Unresolved + + Unresolved data leak incidents + + +
{reportData.n_dataleak.unresolved.potential_stealer}
+
+ Including {reportData.n_dataleak.unresolved.domain_stealer} domain stealer + and {reportData.n_dataleak.unresolved.other_stealer} other leaks +
+
+
+ ) +} diff --git a/resources/js/Components/Dashboard/Overview/OverviewCertificatesCard.tsx b/resources/js/Components/Dashboard/Overview/OverviewCertificatesCard.tsx new file mode 100644 index 0000000..cbd5fce --- /dev/null +++ b/resources/js/Components/Dashboard/Overview/OverviewCertificatesCard.tsx @@ -0,0 +1,23 @@ +import {SecuritySummaryReportResultType} from "@/types/security-summary"; +import {Card, CardContent, CardDescription, CardHeader, CardTitle} from "@/Components/ui/card"; +import {LockIcon} from "lucide-react"; +import React from "react"; + +export default function OverviewCertificatesCard({ reportData }: { reportData: SecuritySummaryReportResultType }) { + return ( + + + + + Certificates + + Number of active and expired certificates + + +
Active: {reportData.n_cert_attivi}
+
Expired: {reportData.n_cert_scaduti}
+
+
+ ) +} diff --git a/resources/js/Components/Dashboard/Overview/OverviewDataLeaksCard.tsx b/resources/js/Components/Dashboard/Overview/OverviewDataLeaksCard.tsx new file mode 100644 index 0000000..443a3e1 --- /dev/null +++ b/resources/js/Components/Dashboard/Overview/OverviewDataLeaksCard.tsx @@ -0,0 +1,26 @@ +import {SecuritySummaryReportResultType} from "@/types/security-summary"; +import {Card, CardContent, CardDescription, CardHeader, CardTitle} from "@/Components/ui/card"; +import {Database} from "lucide-react"; +import React from "react"; + +export default function OverviewDataLeaksCard({ reportData }: { reportData: SecuritySummaryReportResultType }) { + return ( + + + + + Data Leaks + + Total data leak incidents + + +
{reportData.n_dataleak.total.potential_stealer}
+
+ Including {reportData.n_dataleak.total.domain_stealer} domain stealer + and {reportData.n_dataleak.total.other_stealer} other leaks +
+
+
+ ) +} diff --git a/resources/js/Components/Dashboard/Overview/OverviewEmailSecurityCard.tsx b/resources/js/Components/Dashboard/Overview/OverviewEmailSecurityCard.tsx new file mode 100644 index 0000000..8017a18 --- /dev/null +++ b/resources/js/Components/Dashboard/Overview/OverviewEmailSecurityCard.tsx @@ -0,0 +1,31 @@ +import {SecuritySummaryReportResultType} from "@/types/security-summary"; +import {Card, CardContent, CardDescription, CardHeader, CardTitle} from "@/Components/ui/card"; +import {LockIcon} from "lucide-react"; +import React from "react"; + +export default function OverviewEmailSecurityCard({ reportData }: { reportData: SecuritySummaryReportResultType }) { + return ( + + + + + Email Security + + Email security overview + + +
{reportData.email_security.spoofable}
+
+ DMARC Policy: {reportData.email_security.dmarc_policy} +
+
+ Black List Detections: {reportData.email_security.blacklist_detections} and + Black Lists Total List: {reportData.email_security.blacklist_total_list} +
+
+
+ ) +} diff --git a/resources/js/Components/Dashboard/Overview/OverviewNetworkAssetsCard.tsx b/resources/js/Components/Dashboard/Overview/OverviewNetworkAssetsCard.tsx new file mode 100644 index 0000000..143338e --- /dev/null +++ b/resources/js/Components/Dashboard/Overview/OverviewNetworkAssetsCard.tsx @@ -0,0 +1,26 @@ +import {SecuritySummaryReportResultType} from "@/types/security-summary"; +import {Card, CardContent, CardDescription, CardHeader, CardTitle} from "@/Components/ui/card"; +import {Globe} from "lucide-react"; +import React from "react"; + +export default function OverviewNetworkAssetsCard({ reportData }: { reportData: SecuritySummaryReportResultType }) { + + return ( + + + + + Network Assets + + Total assets and IP addresses + + +
{reportData.n_asset}
+
+ IPv4: {reportData.unique_ipv4} + IPv6: {reportData.unique_ipv6} +
+
+
+ ) +} diff --git a/resources/js/Components/Dashboard/Overview/OverviewSimilarDomainsCard.tsx b/resources/js/Components/Dashboard/Overview/OverviewSimilarDomainsCard.tsx new file mode 100644 index 0000000..7f2bb87 --- /dev/null +++ b/resources/js/Components/Dashboard/Overview/OverviewSimilarDomainsCard.tsx @@ -0,0 +1,21 @@ +import {SecuritySummaryReportResultType} from "@/types/security-summary"; +import {Card, CardContent, CardDescription, CardHeader, CardTitle} from "@/Components/ui/card"; +import {Globe} from "lucide-react"; +import React from "react"; + +export default function OverviewSimilarDomainsCard({ reportData }: { reportData: SecuritySummaryReportResultType }) { + return ( + + + + + Similar Domains + + Number of similar Domains + + +
{reportData.n_similar_domains}
+
+
+ ) +} diff --git a/resources/js/Components/Dashboard/Overview/OverviewVulnerabilityScoreCard.tsx b/resources/js/Components/Dashboard/Overview/OverviewVulnerabilityScoreCard.tsx new file mode 100644 index 0000000..a0cdbb2 --- /dev/null +++ b/resources/js/Components/Dashboard/Overview/OverviewVulnerabilityScoreCard.tsx @@ -0,0 +1,35 @@ +import {SecuritySummaryReportResultType} from "@/types/security-summary"; +import {Card, CardContent, CardDescription, CardHeader, CardTitle} from "@/Components/ui/card"; +import {ShieldAlert} from "lucide-react"; +import {Progress} from "@/Components/ui/progress"; +import React from "react"; + +export default function OverviewVulnerabilityScoreCard({ reportData }: { reportData: SecuritySummaryReportResultType }) { + return ( + + + + + Vulnerability Score + + Active and passive vulnerability scores + + +
+
+
Active Score
+ +
{reportData.vulnerability_score_active}% +
+
+
+
Passive Score
+ +
{reportData.vulnerability_score_passive}% +
+
+
+
+
+ ) +} diff --git a/resources/js/Components/Dashboard/Services/ServicesCdnCard.tsx b/resources/js/Components/Dashboard/Services/ServicesCdnCard.tsx new file mode 100644 index 0000000..7e749c1 --- /dev/null +++ b/resources/js/Components/Dashboard/Services/ServicesCdnCard.tsx @@ -0,0 +1,30 @@ +import {SecuritySummaryReportResultType} from "@/types/security-summary"; +import {Card, CardContent, CardHeader, CardTitle} from "@/Components/ui/card"; +import {DatabaseZap} from "lucide-react"; +import React from "react"; + +export default function ServicesCdnCard({ reportData }: { reportData: SecuritySummaryReportResultType }) { + return ( + + + + + CDN + + + +
{reportData.cdn.count}
+
+
CDN assets:
+
+ {reportData.cdn.assets.map((cdn_asset,index) => ( + {cdn_asset} + ))} +
+ +
+
+
+ ) +} diff --git a/resources/js/Components/PortExposureAnalysis.tsx b/resources/js/Components/Dashboard/Services/ServicesPortExposureCard.tsx similarity index 94% rename from resources/js/Components/PortExposureAnalysis.tsx rename to resources/js/Components/Dashboard/Services/ServicesPortExposureCard.tsx index d244114..9d4424b 100644 --- a/resources/js/Components/PortExposureAnalysis.tsx +++ b/resources/js/Components/Dashboard/Services/ServicesPortExposureCard.tsx @@ -9,9 +9,8 @@ import { } from "@/Components/ui/card"; import { SecuritySummaryReportResultType } from "@/types/security-summary"; -export default function PortExposureAnalysis({ reportData }: { reportData: SecuritySummaryReportResultType }) { +export default function ServicesPortExposureCard({ reportData }: { reportData: SecuritySummaryReportResultType }) { - // Transform n_port data for chart const portData = Object.entries(reportData.n_port).map(([port, data]) => ({ name: `Port ${port}`, value: data.n @@ -47,6 +46,9 @@ export default function PortExposureAnalysis({ reportData }: { reportData: Secur className="fill-primary" /> { if (active && payload && payload.length) { return ( diff --git a/resources/js/Components/Dashboard/Services/ServicesWafCard.tsx b/resources/js/Components/Dashboard/Services/ServicesWafCard.tsx new file mode 100644 index 0000000..717c757 --- /dev/null +++ b/resources/js/Components/Dashboard/Services/ServicesWafCard.tsx @@ -0,0 +1,30 @@ +import {SecuritySummaryReportResultType} from "@/types/security-summary"; +import {Card, CardContent, CardHeader, CardTitle} from "@/Components/ui/card"; +import {BrickWall} from "lucide-react"; +import React from "react"; + +export default function ServicesWafCard({ reportData }: { reportData: SecuritySummaryReportResultType }) { + return ( + + + + + WAF + + + +
{reportData.waf.count}
+
+
WAF assets:
+
+ {reportData.waf.assets.map((waf_asset,index) => ( + {waf_asset} + ))} +
+ +
+
+
+ ) +} diff --git a/resources/js/Components/Dashboard/Vulnerabilities/VulnerabilitiesActiveCard.tsx b/resources/js/Components/Dashboard/Vulnerabilities/VulnerabilitiesActiveCard.tsx new file mode 100644 index 0000000..7f247bf --- /dev/null +++ b/resources/js/Components/Dashboard/Vulnerabilities/VulnerabilitiesActiveCard.tsx @@ -0,0 +1,90 @@ +import React, { useState, useMemo } from 'react'; +import { + Card, + CardContent, + CardDescription, + CardHeader, + CardTitle, +} from "@/Components/ui/card"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/Components/ui/select"; +import {SecuritySummaryReportResultType} from "@/types/security-summary"; +import VulnerabilityPieChart from "@/Components/VulnerabilityPieChart"; + +export default function VulnerabilitiesActiveCard({reportData}: { reportData: SecuritySummaryReportResultType }) { + const vulnerabilityData = useMemo(() => [ + { name: 'Critical', value: reportData.n_vulns.active.critical, fill: 'hsl(var(--chart-1))' }, + { name: 'High', value: reportData.n_vulns.active.high, fill: 'hsl(var(--chart-2))' }, + { name: 'Medium', value: reportData.n_vulns.active.medium, fill: 'hsl(var(--chart-3))' }, + ], [reportData]); + + const [activeMetric, setActiveMetric] = useState(vulnerabilityData[0].name); + + const activeIndex = useMemo( + () => vulnerabilityData.findIndex((item) => item.name === activeMetric), + [activeMetric, vulnerabilityData] + ); + + const metrics = useMemo(() => vulnerabilityData.map((item) => item.name), [vulnerabilityData]); + + const chartConfig: any = { + 'Critical': { + label: "Critical", + color: 'hsl(var(--chart-1))' + }, + 'High': { + label: "High", + color: 'hsl(var(--chart-2))' + }, + 'Medium': { + label: "Medium", + color: 'hsl(var(--chart-3))' + }, + }; + + return ( + + +
+ Active Vulnerabilities + Number of Active Vulnerabilities +
+ +
+ + + +
+ ); +} diff --git a/resources/js/Components/Dashboard/Vulnerabilities/VulnerabilitiesPassiveCard.tsx b/resources/js/Components/Dashboard/Vulnerabilities/VulnerabilitiesPassiveCard.tsx new file mode 100644 index 0000000..01420c0 --- /dev/null +++ b/resources/js/Components/Dashboard/Vulnerabilities/VulnerabilitiesPassiveCard.tsx @@ -0,0 +1,85 @@ +import React, { useState, useMemo } from 'react'; +import { + Card, + CardContent, + CardDescription, + CardHeader, + CardTitle, +} from "@/Components/ui/card"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/Components/ui/select"; +import {SecuritySummaryReportResultType} from "@/types/security-summary"; +import VulnerabilityPieChart from "@/Components/VulnerabilityPieChart"; + +export default function VulnerabilitiesPassiveCard({reportData}: { reportData: SecuritySummaryReportResultType }) { + const vulnerabilityData = useMemo(() => [ + { name: 'High', value: reportData.n_vulns.passive.high, fill: 'hsl(var(--chart-4))' }, + { name: 'Medium', value: reportData.n_vulns.passive.medium, fill: 'hsl(var(--chart-5))' } + ], [reportData]); + + const [activeMetric, setActiveMetric] = useState(vulnerabilityData[0].name); + + const activeIndex = useMemo( + () => vulnerabilityData.findIndex((item) => item.name === activeMetric), + [activeMetric, vulnerabilityData] + ); + + const metrics = useMemo(() => vulnerabilityData.map((item) => item.name), [vulnerabilityData]); + + const chartConfig: any = { + 'High': { + label: "High", + color: 'hsl(var(--chart-4))' + }, + 'Medium': { + label: "Medium", + color: 'hsl(var(--chart-5))' + } + }; + + return ( + + +
+ Passive Vulnerabilities + Number of Passive Vulnerabilities +
+ +
+ + + +
+ ); +} diff --git a/resources/js/Components/NumberOfVulnerabilitiesPieChart.tsx b/resources/js/Components/NumberOfVulnerabilitiesPieChart.tsx deleted file mode 100644 index ffd54ed..0000000 --- a/resources/js/Components/NumberOfVulnerabilitiesPieChart.tsx +++ /dev/null @@ -1,157 +0,0 @@ -import React, { useState, useMemo } from 'react'; -import { PieChart, Pie, Sector, Label } from 'recharts'; -import { PieSectorDataItem } from "recharts/types/polar/Pie"; -import { - Card, - CardContent, - CardDescription, - CardHeader, - CardTitle, -} from "@/Components/ui/card"; -import { - Select, - SelectContent, - SelectItem, - SelectTrigger, - SelectValue, -} from "@/Components/ui/select"; -import {SecuritySummaryReportResultType} from "@/types/security-summary"; - -export default function NumberOfVulnerabilitiesPieChart({reportData}: { reportData: SecuritySummaryReportResultType }) { - const vulnerabilityData = useMemo(() => [ - { name: 'Active Critical', value: reportData.n_vulns.active.critical, fill: 'hsl(var(--chart-1))' }, - { name: 'Active High', value: reportData.n_vulns.active.high, fill: 'hsl(var(--chart-2))' }, - { name: 'Active Medium', value: reportData.n_vulns.active.medium, fill: 'hsl(var(--chart-3))' }, - { name: 'Passive High', value: reportData.n_vulns.passive.high, fill: 'hsl(var(--chart-4))' }, - { name: 'Passive Medium', value: reportData.n_vulns.passive.medium, fill: 'hsl(var(--chart-5))' } - ], [reportData]); - - const [activeMetric, setActiveMetric] = useState(vulnerabilityData[0].name); - - const activeIndex = useMemo( - () => vulnerabilityData.findIndex((item) => item.name === activeMetric), - [activeMetric, vulnerabilityData] - ); - - const metrics = useMemo(() => vulnerabilityData.map((item) => item.name), [vulnerabilityData]); - - const chartConfig: any = { - 'Active Critical': { - label: "Active Critical", - color: 'hsl(var(--chart-1))' - }, - 'Active High': { - label: "Active High", - color: 'hsl(var(--chart-2))' - }, - 'Active Medium': { - label: "Active Medium", - color: 'hsl(var(--chart-3))' - }, - 'Passive High': { - label: "Passive High", - color: 'hsl(var(--chart-4))' - }, - 'Passive Medium': { - label: "Passive Medium", - color: 'hsl(var(--chart-5))' - } - }; - - return ( - - -
- Number of Vulnerabilities - Vulnerabilities details -
- -
- -
- - ( - - - - - )} - > - - -
-
-
- ); -} diff --git a/resources/js/Components/SecurityScoresOverviewBarChart.tsx b/resources/js/Components/SecurityScoresOverviewBarChart.tsx index bf4402b..68a8e3c 100644 --- a/resources/js/Components/SecurityScoresOverviewBarChart.tsx +++ b/resources/js/Components/SecurityScoresOverviewBarChart.tsx @@ -27,9 +27,7 @@ export default function SecurityScoresOverviewBarChart({ reportData }: { reportD { metric: 'Spoofing', score: reportData.spoofing_score }, { metric: 'Open Port', score: reportData.open_ports_score }, { metric: 'Blacklist', score: reportData.blacklist_score }, - { metric: 'Certificate', score: reportData.certificate_score }, - { metric: 'Active Vulnerability', score: reportData.vulnerability_score_active }, - { metric: 'Passive Vulnerability', score: reportData.vulnerability_score_passive }, + { metric: 'Certificate', score: reportData.certificate_score } ], [reportData]); @@ -43,7 +41,6 @@ export default function SecurityScoresOverviewBarChart({ reportData }: { reportD }, } satisfies ChartConfig; - // Calculate average score and trend const averageScore = useMemo(() => { const sum = chartData.reduce((acc, curr) => acc + curr.score, 0); return Math.round(sum / chartData.length); diff --git a/resources/js/Components/VulnerabilityPieChart.tsx b/resources/js/Components/VulnerabilityPieChart.tsx new file mode 100644 index 0000000..56a1117 --- /dev/null +++ b/resources/js/Components/VulnerabilityPieChart.tsx @@ -0,0 +1,78 @@ +import {SecuritySummaryReportResultType} from "@/types/security-summary"; +import {Label, Pie, PieChart, Sector} from "recharts"; +import {PieSectorDataItem} from "recharts/types/polar/Pie"; +import React from "react"; + +type ChartData = { + name: string, + value: number, + fill: string +} +export default function VulnerabilityPieChart({ + vulnerabilityData, activeIndex +}: { + vulnerabilityData: ChartData[], + activeIndex: number +}) { + return ( + <> +
+ + ( + + + + + )} + > + + +
+ + ) +} diff --git a/resources/js/Components/ui/calendar.tsx b/resources/js/Components/ui/calendar.tsx new file mode 100644 index 0000000..4d6579c --- /dev/null +++ b/resources/js/Components/ui/calendar.tsx @@ -0,0 +1,70 @@ +import * as React from "react" +import { ChevronLeft, ChevronRight } from "lucide-react" +import { DayPicker } from "react-day-picker" + +import { cn } from "@/lib/utils" +import { buttonVariants } from "@/components/ui/button" + +export type CalendarProps = React.ComponentProps + +function Calendar({ + className, + classNames, + showOutsideDays = true, + ...props +}: CalendarProps) { + return ( + .day-range-end)]:rounded-r-md [&:has(>.day-range-start)]:rounded-l-md first:[&:has([aria-selected])]:rounded-l-md last:[&:has([aria-selected])]:rounded-r-md" + : "[&:has([aria-selected])]:rounded-md" + ), + day: cn( + buttonVariants({ variant: "ghost" }), + "h-8 w-8 p-0 font-normal aria-selected:opacity-100" + ), + day_range_start: "day-range-start", + day_range_end: "day-range-end", + day_selected: + "bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground focus:bg-primary focus:text-primary-foreground", + day_today: "bg-accent text-accent-foreground", + day_outside: + "day-outside text-muted-foreground aria-selected:bg-accent/50 aria-selected:text-muted-foreground", + day_disabled: "text-muted-foreground opacity-50", + day_range_middle: + "aria-selected:bg-accent aria-selected:text-accent-foreground", + day_hidden: "invisible", + ...classNames, + }} + components={{ + IconLeft: ({ ...props }) => , + IconRight: ({ ...props }) => , + }} + {...props} + /> + ) +} +Calendar.displayName = "Calendar" + +export { Calendar } diff --git a/resources/js/Components/ui/checkbox.tsx b/resources/js/Components/ui/checkbox.tsx new file mode 100644 index 0000000..0a6a9a5 --- /dev/null +++ b/resources/js/Components/ui/checkbox.tsx @@ -0,0 +1,28 @@ +import * as React from "react" +import * as CheckboxPrimitive from "@radix-ui/react-checkbox" +import { Check } from "lucide-react" + +import { cn } from "@/lib/utils" + +const Checkbox = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + + + +)) +Checkbox.displayName = CheckboxPrimitive.Root.displayName + +export { Checkbox } diff --git a/resources/js/Components/ui/dropdown-menu.tsx b/resources/js/Components/ui/dropdown-menu.tsx new file mode 100644 index 0000000..9ff6568 --- /dev/null +++ b/resources/js/Components/ui/dropdown-menu.tsx @@ -0,0 +1,199 @@ +import * as React from "react" +import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu" +import { Check, ChevronRight, Circle } from "lucide-react" + +import { cn } from "@/lib/utils" + +const DropdownMenu = DropdownMenuPrimitive.Root + +const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger + +const DropdownMenuGroup = DropdownMenuPrimitive.Group + +const DropdownMenuPortal = DropdownMenuPrimitive.Portal + +const DropdownMenuSub = DropdownMenuPrimitive.Sub + +const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup + +const DropdownMenuSubTrigger = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + inset?: boolean + } +>(({ className, inset, children, ...props }, ref) => ( + + {children} + + +)) +DropdownMenuSubTrigger.displayName = + DropdownMenuPrimitive.SubTrigger.displayName + +const DropdownMenuSubContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DropdownMenuSubContent.displayName = + DropdownMenuPrimitive.SubContent.displayName + +const DropdownMenuContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, sideOffset = 4, ...props }, ref) => ( + + + +)) +DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName + +const DropdownMenuItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + inset?: boolean + } +>(({ className, inset, ...props }, ref) => ( + svg]:size-4 [&>svg]:shrink-0", + inset && "pl-8", + className + )} + {...props} + /> +)) +DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName + +const DropdownMenuCheckboxItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, checked, ...props }, ref) => ( + + + + + + + {children} + +)) +DropdownMenuCheckboxItem.displayName = + DropdownMenuPrimitive.CheckboxItem.displayName + +const DropdownMenuRadioItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + + + + + {children} + +)) +DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName + +const DropdownMenuLabel = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + inset?: boolean + } +>(({ className, inset, ...props }, ref) => ( + +)) +DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName + +const DropdownMenuSeparator = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName + +const DropdownMenuShortcut = ({ + className, + ...props +}: React.HTMLAttributes) => { + return ( + + ) +} +DropdownMenuShortcut.displayName = "DropdownMenuShortcut" + +export { + DropdownMenu, + DropdownMenuTrigger, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuCheckboxItem, + DropdownMenuRadioItem, + DropdownMenuLabel, + DropdownMenuSeparator, + DropdownMenuShortcut, + DropdownMenuGroup, + DropdownMenuPortal, + DropdownMenuSub, + DropdownMenuSubContent, + DropdownMenuSubTrigger, + DropdownMenuRadioGroup, +} diff --git a/resources/js/Components/ui/input.tsx b/resources/js/Components/ui/input.tsx new file mode 100644 index 0000000..69b64fb --- /dev/null +++ b/resources/js/Components/ui/input.tsx @@ -0,0 +1,22 @@ +import * as React from "react" + +import { cn } from "@/lib/utils" + +const Input = React.forwardRef>( + ({ className, type, ...props }, ref) => { + return ( + + ) + } +) +Input.displayName = "Input" + +export { Input } diff --git a/resources/js/Components/ui/table.tsx b/resources/js/Components/ui/table.tsx new file mode 100644 index 0000000..c0df655 --- /dev/null +++ b/resources/js/Components/ui/table.tsx @@ -0,0 +1,120 @@ +import * as React from "react" + +import { cn } from "@/lib/utils" + +const Table = React.forwardRef< + HTMLTableElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+ + +)) +Table.displayName = "Table" + +const TableHeader = React.forwardRef< + HTMLTableSectionElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( + +)) +TableHeader.displayName = "TableHeader" + +const TableBody = React.forwardRef< + HTMLTableSectionElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( + +)) +TableBody.displayName = "TableBody" + +const TableFooter = React.forwardRef< + HTMLTableSectionElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( + tr]:last:border-b-0", + className + )} + {...props} + /> +)) +TableFooter.displayName = "TableFooter" + +const TableRow = React.forwardRef< + HTMLTableRowElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( + +)) +TableRow.displayName = "TableRow" + +const TableHead = React.forwardRef< + HTMLTableCellElement, + React.ThHTMLAttributes +>(({ className, ...props }, ref) => ( +
[role=checkbox]]:translate-y-[2px]", + className + )} + {...props} + /> +)) +TableHead.displayName = "TableHead" + +const TableCell = React.forwardRef< + HTMLTableCellElement, + React.TdHTMLAttributes +>(({ className, ...props }, ref) => ( + [role=checkbox]]:translate-y-[2px]", + className + )} + {...props} + /> +)) +TableCell.displayName = "TableCell" + +const TableCaption = React.forwardRef< + HTMLTableCaptionElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)) +TableCaption.displayName = "TableCaption" + +export { + Table, + TableHeader, + TableBody, + TableFooter, + TableHead, + TableRow, + TableCell, + TableCaption, +} diff --git a/resources/js/Pages/Dashboard.tsx b/resources/js/Pages/Dashboard.tsx index c3bcf7c..936accd 100644 --- a/resources/js/Pages/Dashboard.tsx +++ b/resources/js/Pages/Dashboard.tsx @@ -4,36 +4,43 @@ import { Card, CardContent, CardHeader, - CardTitle, - CardDescription + CardTitle } from '@/Components/ui/card'; import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/Components/ui/tabs'; import { Button } from "@/Components/ui/button"; -import { Progress } from '@/Components/ui/progress'; -import { Alert, AlertDescription, AlertTitle } from '@/Components/ui/alert'; -import { ShieldAlert, Globe, Database, ChevronLeft, ChevronRight, Check, Copy } from 'lucide-react'; +import { Alert, AlertDescription } from '@/Components/ui/alert'; +import { ShieldAlert, ChevronLeft, ChevronRight } from 'lucide-react'; import Markdown from 'react-markdown'; import { SecuritySummaryReportResultType, SecuritySummaryResponseType, } from '@/types/security-summary'; -import NumberOfVulnerabilitiesPieChart from "@/Components/NumberOfVulnerabilitiesPieChart"; +import VulnerabilitiesActiveCard from "@/Components/Dashboard/Vulnerabilities/VulnerabilitiesActiveCard"; +import VulnerabilitiesPassiveCard from "@/Components/Dashboard/Vulnerabilities/VulnerabilitiesPassiveCard"; import SecurityScoresOverviewBarChart from "@/Components/SecurityScoresOverviewBarChart"; -import PortExposureAnalysis from "@/Components/PortExposureAnalysis"; -import { useClipboard } from "use-clipboard-copy" -import DashboardHeader from "@/Components/DashboardHeader"; +import ServicesPortExposureCard from "@/Components/Dashboard/Services/ServicesPortExposureCard"; +import DashboardHeader from "@/Components/Dashboard/DashboardHeader"; +import OverviewNetworkAssetsCard from "@/Components/Dashboard/Overview/OverviewNetworkAssetsCard"; +import OverviewSimilarDomainsCard from "@/Components/Dashboard/Overview/OverviewSimilarDomainsCard"; +import OverviewEmailSecurityCard from "@/Components/Dashboard/Overview/OverviewEmailSecurityCard"; +import OverviewCertificatesCard from "@/Components/Dashboard/Overview/OverviewCertificatesCard"; +import OverviewDataLeaksCard from "@/Components/Dashboard/Overview/OverviewDataLeaksCard"; +import ServicesWafCard from "@/Components/Dashboard/Services/ServicesWafCard"; +import ServicesCdnCard from "@/Components/Dashboard/Services/ServicesCdnCard"; +import LeaksEnumerationCard from "@/Components/Dashboard/Leaks/LeaksEnumerationCard"; +import LeaksResolvedCard from "@/Components/Dashboard/Leaks/LeaksResolvedCard"; +import LeaksUnresolvedCard from "@/Components/Dashboard/Leaks/LeaksUnresolvedCard"; +import OverviewVulnerabilityScoreCard from "@/Components/Dashboard/Overview/OverviewVulnerabilityScoreCard"; - -export default function Dashboard() { +export default function Dashboard({ page }: { page:number }) { const [securitySummaryResponse, setSecuritySummaryResponse] = useState(null); const [reportData, setReportData] = useState(null); - const [currentPage, setCurrentPage] = useState(0); + const [currentPage, setCurrentPage] = useState(page); useEffect(() => { axios.get('/api/v1/security/summary') .then(response => { setSecuritySummaryResponse(response.data); - // Set initial report data setReportData(response.data.results[0] ?? null); }) .catch(error => { @@ -41,7 +48,6 @@ export default function Dashboard() { }); }, []); - // Handle page changes useEffect(() => { if (securitySummaryResponse) { setReportData(securitySummaryResponse.results[currentPage] ?? null); @@ -62,9 +68,9 @@ export default function Dashboard() { return (
- + - + Overview Vulnerabilities @@ -72,74 +78,17 @@ export default function Dashboard() { Data Leaks - -
- - - - - Vulnerability Score - - Active and passive vulnerability scores - - -
-
-
Active Score
- -
{reportData.vulnerability_score_active}% -
-
-
-
Passive Score
- -
{reportData.vulnerability_score_passive}% -
-
-
-
-
- - - - - - Network Assets - - Total assets and IP addresses - - -
{reportData.n_asset}
-
- IPv4: {reportData.unique_ipv4} - IPv6: {reportData.unique_ipv6} -
-
-
- - - - - - Data Leaks - - Unresolved data leak incidents - - -
{reportData.n_dataleak.unresolved.potential_stealer}
-
- Including {reportData.n_dataleak.unresolved.domain_stealer} domain stealer - and {reportData.n_dataleak.unresolved.other_stealer} other leaks -
-
-
+ +
+

Overview

- -
- - - +
+ + + + + +
@@ -172,33 +121,66 @@ export default function Dashboard() { -
- + -
- Page {currentPage + 1} of {securitySummaryResponse?.results.length} -
+ +
+

Data Leaks Details

+
+
+ + + +
+
- + + +
+

Data Leaks Details

+
+
+ + +
+
+ + +
+

Data Leaks Details

+
+
+ + +
+
+ + +
+ Page {currentPage + 1} of {securitySummaryResponse?.results.length} +
+ + +
); }; diff --git a/resources/js/Pages/Home.tsx b/resources/js/Pages/Home.tsx new file mode 100644 index 0000000..188d592 --- /dev/null +++ b/resources/js/Pages/Home.tsx @@ -0,0 +1,85 @@ +import React, { useEffect, useState } from 'react'; +import axios from 'axios'; +import { + SecuritySummaryResponseType, +} from '@/types/security-summary'; +import { TextSearchIcon } from 'lucide-react'; +import { + Table, + TableBody, + TableCaption, + TableCell, + TableFooter, + TableHead, + TableHeader, + TableRow, +} from "@/Components/ui/table" +import {Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle} from "@/Components/ui/card"; + +export default function Home() { + const [securitySummaryResponse, setSecuritySummaryResponse] = useState(null); + + useEffect(() => { + axios.get('/api/v1/security/summary') + .then(response => { + setSecuritySummaryResponse(response.data); + }) + .catch(error => { + console.error("Error fetching the report data", error); + }); + }, []); + + + return ( +
+ + + Scan Reports + Pick a scan to see the dashboard, you can also navigate trough dashboard using prev and next arrow at the end of each report overview + + + + + + Domain + UUID + Method + Score + + + + + {securitySummaryResponse?.results.map((data, index) => ( + + + {data.domain_name} + + {data.idsummary} + {data.creation_date} + {data.risk_score} + + + + + + + + ))} + +
+
+
+ + + + Upload Password Leak + + + + --todo + + + +
+ ); +}; diff --git a/routes/web.php b/routes/web.php index 3d4491d..f9cdf28 100644 --- a/routes/web.php +++ b/routes/web.php @@ -6,9 +6,11 @@ use Illuminate\Support\Facades\Route; use Inertia\Inertia; Route::get('/', function () { - return redirect('/dashboard'); + return Inertia::render('Home'); }); -Route::get('/dashboard', function () { - return Inertia::render('Dashboard'); +Route::get('/report/{page}/dashboard', function (int $page = 0) { + return Inertia::render('Dashboard', [ + 'page' => $page + ]); })->name('dashboard');