From f2fbccc759dea25f9ff48ded77f89db0a96fe827 Mon Sep 17 00:00:00 2001 From: Mcat12 Date: Thu, 13 Dec 2018 17:52:35 -0500 Subject: [PATCH] Validate DNS settings, and save them when Apply is clicked Signed-off-by: Mcat12 --- .../settings/ConditionalForwardingSettings.js | 12 +- src/components/settings/DNSInfo.js | 125 +++++++++++++++--- src/util/api.js | 3 + 3 files changed, 124 insertions(+), 16 deletions(-) diff --git a/src/components/settings/ConditionalForwardingSettings.js b/src/components/settings/ConditionalForwardingSettings.js index 03a1a5f..39daf87 100644 --- a/src/components/settings/ConditionalForwardingSettings.js +++ b/src/components/settings/ConditionalForwardingSettings.js @@ -12,7 +12,13 @@ import React, { Fragment } from "react"; import PropTypes from "prop-types"; import { Col, FormGroup, Input, Label } from "reactstrap"; -const ConditionalForwardingSettings = ({ settings, onUpdate, t }) => ( +const ConditionalForwardingSettings = ({ + settings, + onUpdate, + isRouterIpValid, + isDomainValid, + t +}) => ( @@ -47,6 +54,7 @@ const ConditionalForwardingSettings = ({ settings, onUpdate, t }) => ( disabled={!settings.enabled} value={settings.domain} onChange={e => onUpdate({ ...settings, domain: e.target.value })} + invalid={!isDomainValid} /> @@ -56,6 +64,8 @@ const ConditionalForwardingSettings = ({ settings, onUpdate, t }) => ( ConditionalForwardingSettings.propTypes = { settings: PropTypes.object.isRequired, onUpdate: PropTypes.func.isRequired, + isRouterIpValid: PropTypes.bool.isRequired, + isDomainValid: PropTypes.bool.isRequired, t: PropTypes.func.isRequired }; diff --git a/src/components/settings/DNSInfo.js b/src/components/settings/DNSInfo.js index c00f451..0777c28 100644 --- a/src/components/settings/DNSInfo.js +++ b/src/components/settings/DNSInfo.js @@ -16,9 +16,15 @@ import DnsList from "./DnsList"; import { Button, Col, Form, FormGroup } from "reactstrap"; import ConditionalForwardingSettings from "./ConditionalForwardingSettings"; import DnsOptionSettings from "./DnsOptionSettings"; +import Alert from "../common/Alert"; +import { isValidHostname, isValidIpv4 } from "../../validate"; class DNSInfo extends Component { state = { + alertMessage: "", + alertType: "", + showAlert: false, + processing: false, upstreamDns: [], conditionalForwarding: { enabled: false, @@ -33,17 +39,9 @@ class DNSInfo extends Component { } }; - constructor(props) { - super(props); - this.updateDNSInfo = this.updateDNSInfo.bind(this); - } - - updateDNSInfo() { - this.updateHandler = makeCancelable(api.getDNSInfo(), { - repeat: this.updateDNSInfo, - interval: 600000 - }); - this.updateHandler.promise + loadDNSInfo = () => { + this.loadHandler = makeCancelable(api.getDNSInfo()); + this.loadHandler.promise .then(res => { this.setState({ upstreamDns: res.upstream_dns, @@ -61,14 +59,14 @@ class DNSInfo extends Component { }); }) .catch(ignoreCancel); - } + }; componentDidMount() { - this.updateDNSInfo(); + this.loadDNSInfo(); } componentWillUnmount() { - this.updateHandler.cancel(); + this.loadHandler.cancel(); } handleUpstreamAdd = upstream => { @@ -91,15 +89,105 @@ class DNSInfo extends Component { this.setState({ options }); }; + /** + * Save changes to DNS settings + * + * @param e the submit event + */ saveSettings = e => { e.preventDefault(); + + const { t } = this.props; + + this.setState({ + alertMessage: t("Processing..."), + alertType: "info", + showAlert: true, + processing: true + }); + + this.updateHandler = makeCancelable( + api.updateDNSInfo({ + upstream_dns: this.state.upstreamDns, + conditional_forwarding: { + enabled: this.state.conditionalForwarding.enabled, + router_ip: this.state.conditionalForwarding.routerIp, + domain: this.state.conditionalForwarding.domain + }, + options: { + fqdn_required: this.state.options.fqdnRequired, + bogus_priv: this.state.options.bogusPriv, + dnssec: this.state.options.dnssec, + listening_type: this.state.options.listeningType + } + }) + ); + this.updateHandler.promise + .then(() => { + this.setState({ + alertMessage: t("Successfully saved settings"), + alertType: "success", + showAlert: true, + processing: false + }); + }) + .catch(ignoreCancel) + .catch(error => { + let message = ""; + + if (error instanceof Error) { + message = error.message; + } else { + // Translate the API's error message + message = t("API Error: {{error}}", { + error: t(error.key, error.data) + }); + } + + this.setState({ + alertMessage: message, + alertType: "danger", + showAlert: true, + processing: false + }); + }); + }; + + isCFSettingValid = (value, validator) => { + return ( + (!this.state.conditionalForwarding.enabled && value.length === 0) || + validator(value) + ); + }; + + hideAlert = () => { + this.setState({ showAlert: false }); }; render() { const { t } = this.props; + const isRouterIpValid = this.isCFSettingValid( + this.state.conditionalForwarding.routerIp, + isValidIpv4 + ); + + const isDomainValid = this.isCFSettingValid( + this.state.conditionalForwarding.domain, + isValidHostname + ); + + const alert = this.state.showAlert ? ( + + ) : null; + return (
+ {alert}

{t("Upstream DNS Servers")}

@@ -114,6 +202,8 @@ class DNSInfo extends Component {

{t("DNS Options")}

@@ -124,7 +214,12 @@ class DNSInfo extends Component { />
- +
); } diff --git a/src/util/api.js b/src/util/api.js index 60b4251..b7d91f5 100644 --- a/src/util/api.js +++ b/src/util/api.js @@ -84,5 +84,8 @@ export default { }, updateDHCPInfo(settings) { return http.put("settings/dhcp", settings); + }, + updateDNSInfo(settings) { + return http.put("settings/dns", settings); } };