From 71277d1e830844767c3302f5b09db5cf687f6bb0 Mon Sep 17 00:00:00 2001 From: Tudor Stanciu Date: Sun, 13 Jul 2025 17:07:48 +0300 Subject: [PATCH] Add IP filtering feature with UI components and translations --- package.json | 2 +- public/locales/en/translations.json | 11 +++ public/locales/ro/translations.json | 11 +++ .../ForwardOptionsAdvancedComponent.js | 7 ++ .../advanced/ipFiltering/IpFilteringCard.js | 26 ++++++ .../advanced/ipFiltering/IpFilteringRules.js | 90 +++++++++++++++++++ .../ipFiltering/IpFilteringSummary.js | 41 +++++++++ .../simple/ForwardOptionsComponent.js | 5 ++ 8 files changed, 192 insertions(+), 1 deletion(-) create mode 100644 src/features/forwards/options/components/advanced/ipFiltering/IpFilteringCard.js create mode 100644 src/features/forwards/options/components/advanced/ipFiltering/IpFilteringRules.js create mode 100644 src/features/forwards/options/components/advanced/ipFiltering/IpFilteringSummary.js diff --git a/package.json b/package.json index a97ec84..980197f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "reverse-proxy-frontend", - "version": "1.4.11", + "version": "1.4.12", "private": true, "description": "Reverse proxy frontend application", "author": { diff --git a/public/locales/en/translations.json b/public/locales/en/translations.json index c362f73..41bb3e4 100644 --- a/public/locales/en/translations.json +++ b/public/locales/en/translations.json @@ -110,6 +110,17 @@ "CertificateChainErrors": "Bypass certificate chain errors", "CertificateChainErrorsDescription": "With this option is enabled, the reverse proxy will not validate the SSL certificate chain of the upstream server. This is useful when the upstream server's certificate chain is incomplete or invalid." } + }, + "IpFiltering": { + "Label": "IP filtering", + "Tooltip": "IPFiltering is used to filter the IP addresses that can access the forward. It can be used to allow or deny access to specific IP addresses or ranges of IP addresses.", + "Mode": "Mode", + "RulesCount": "Rules count", + "Rules": { + "Title": "Rules", + "IpAddress": "IP address", + "Description": "Description" + } } } }, diff --git a/public/locales/ro/translations.json b/public/locales/ro/translations.json index 1c0f941..a0d1e84 100644 --- a/public/locales/ro/translations.json +++ b/public/locales/ro/translations.json @@ -101,6 +101,17 @@ "CertificateChainErrors": "Ocolește erorile lanțului de certificate", "CertificateChainErrorsDescription": "Cu această opțiune este activată, proxy-ul nu va valida lanțul de certificate SSL al serverului din amonte. Acest lucru este util atunci când lanțul de certificate al serverului din amonte este incomplet sau invalid." } + }, + "IpFiltering": { + "Label": "Filtrare IP", + "Tooltip": "Filtrarea IP este utilizată pentru a filtra adresele IP care pot accesa redirecționarea. Poate fi utilizată pentru a permite sau a refuza accesul la anumite adrese IP sau intervale de adrese IP.", + "Mode": "Mod", + "RulesCount": "Număr reguli", + "Rules": { + "Title": "Reguli", + "IpAddress": "Adresă IP", + "Description": "Descriere" + } } } }, diff --git a/src/features/forwards/options/components/advanced/ForwardOptionsAdvancedComponent.js b/src/features/forwards/options/components/advanced/ForwardOptionsAdvancedComponent.js index 6c31c6d..1253594 100644 --- a/src/features/forwards/options/components/advanced/ForwardOptionsAdvancedComponent.js +++ b/src/features/forwards/options/components/advanced/ForwardOptionsAdvancedComponent.js @@ -7,6 +7,7 @@ import KeyOverwriteCard from "./keyOverwrite/KeyOverwriteCard"; import SpecificHeadersCard from "./specificHeaders/SpecificHeadersCard"; import UpstreamSchemeCard from "./upstreamScheme/UpstreamSchemeCard"; import SslPolicyCard from "./sslPolicy/SslPolicyCard"; +import IpFilteringCard from "./ipFiltering/IpFilteringCard"; const ForwardOptionsAdvancedComponent = ({ options }) => { return ( @@ -53,6 +54,12 @@ const ForwardOptionsAdvancedComponent = ({ options }) => {
)} + {options.ipFiltering && ( + <> + +
+ + )} ); }; diff --git a/src/features/forwards/options/components/advanced/ipFiltering/IpFilteringCard.js b/src/features/forwards/options/components/advanced/ipFiltering/IpFilteringCard.js new file mode 100644 index 0000000..6cc8113 --- /dev/null +++ b/src/features/forwards/options/components/advanced/ipFiltering/IpFilteringCard.js @@ -0,0 +1,26 @@ +import React from "react"; +import PropTypes from "prop-types"; +import ExpandableCard from "../../../../../../components/common/ExpandableCard"; +import { useTranslation } from "react-i18next"; +import BlockIcon from "@material-ui/icons/Block"; +import IpFilteringSummary from "./IpFilteringSummary"; + +const IpFilteringCard = ({ data }) => { + const { t } = useTranslation(); + + return ( + } + title={t("Forward.Options.IpFiltering.Label")} + subtitle={t("Forward.Options.IpFiltering.Tooltip")} + expandable={false} + Summary={} + /> + ); +}; + +IpFilteringCard.propTypes = { + data: PropTypes.object.isRequired +}; + +export default IpFilteringCard; diff --git a/src/features/forwards/options/components/advanced/ipFiltering/IpFilteringRules.js b/src/features/forwards/options/components/advanced/ipFiltering/IpFilteringRules.js new file mode 100644 index 0000000..c7129af --- /dev/null +++ b/src/features/forwards/options/components/advanced/ipFiltering/IpFilteringRules.js @@ -0,0 +1,90 @@ +import React from "react"; +import PropTypes from "prop-types"; +import ExpandableCard from "../../../../../../components/common/ExpandableCard"; +import { useTranslation } from "react-i18next"; +import { List } from "@material-ui/icons"; +import { makeStyles } from "@material-ui/core/styles"; +import { + Table, + TableBody, + TableContainer, + TableHead, + TableRow, + Paper +} from "@material-ui/core"; +import styles from "../../../../../../components/common/styles/tableStyles"; +import { + StyledTableCell, + StyledTableRow +} from "../../../../../../components/common/MaterialTable"; +import InputIcon from "@material-ui/icons/Input"; +import BlockIcon from "@material-ui/icons/Block"; + +const useStyles = makeStyles(styles); + +const IpFilteringRules = ({ mode, rules }) => { + const isAllowedMode = mode === "Allow"; + + const classes = useStyles(); + const { t } = useTranslation(); + return ( + } + iconVariant="rounded" + title={t("Forward.Options.IpFiltering.Rules.Title")} + smallHeader + Content={ + + + + + + {t("Forward.Options.IpFiltering.Rules.IpAddress")} + + + {t("Forward.Options.IpFiltering.Rules.Description")} + + + + + <> + {rules.map(rule => { + return ( + + + {isAllowedMode ? ( + + ) : ( + + )} + {rule.ipAddress} + + {rule.description} + + ); + })} + + +
+
+ } + /> + ); +}; + +IpFilteringRules.propTypes = { + mode: PropTypes.string.isRequired, + rules: PropTypes.array.isRequired +}; + +export default IpFilteringRules; diff --git a/src/features/forwards/options/components/advanced/ipFiltering/IpFilteringSummary.js b/src/features/forwards/options/components/advanced/ipFiltering/IpFilteringSummary.js new file mode 100644 index 0000000..0720988 --- /dev/null +++ b/src/features/forwards/options/components/advanced/ipFiltering/IpFilteringSummary.js @@ -0,0 +1,41 @@ +import React from "react"; +import PropTypes from "prop-types"; +import { Grid } from "@material-ui/core"; +import { useTranslation } from "react-i18next"; +import ActiveIcon from "../../../../../../components/common/ActiveIcon"; +import { makeStyles } from "@material-ui/core/styles"; +import styles from "../../../../../../components/common/styles/gridStyles"; +import IpFilteringRules from "./IpFilteringRules"; + +const useStyles = makeStyles(styles); + +const IpFilteringSummary = ({ data }) => { + const { t } = useTranslation(); + const classes = useStyles(); + return ( + <> + + + {`${t("General.Enabled")}: `} + + + + {`${t("Forward.Options.IpFiltering.Mode")}: `} + {data.mode} + + + {`${t("Forward.Options.IpFiltering.RulesCount")}: `} + {data.rules?.length || 0} + + +
+ + + ); +}; + +IpFilteringSummary.propTypes = { + data: PropTypes.object.isRequired +}; + +export default IpFilteringSummary; diff --git a/src/features/forwards/options/components/simple/ForwardOptionsComponent.js b/src/features/forwards/options/components/simple/ForwardOptionsComponent.js index 1373355..4766641 100644 --- a/src/features/forwards/options/components/simple/ForwardOptionsComponent.js +++ b/src/features/forwards/options/components/simple/ForwardOptionsComponent.js @@ -63,6 +63,11 @@ const ForwardOptionsComponent = ({ title, options }) => { label: "Forward.Options.SslPolicy.Label", tooltip: "Forward.Options.SslPolicy.Tooltip", active: !!options.sslPolicy + }, + { + label: "Forward.Options.IpFiltering.Label", + tooltip: "Forward.Options.IpFiltering.Tooltip", + active: !!options.ipFiltering } ], [options]