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]