mirror of
https://github.com/gosticks/web.git
synced 2026-10-06 06:37:07 +00:00
Merge branch 'development' into footer-dev
This commit is contained in:
@@ -11,16 +11,27 @@
|
||||
import React, { Component } from "react";
|
||||
import { translate } from "react-i18next";
|
||||
import { api, ignoreCancel, makeCancelable } from "../../utils";
|
||||
import {
|
||||
Button,
|
||||
Col,
|
||||
Form,
|
||||
FormGroup,
|
||||
Input,
|
||||
InputGroup,
|
||||
InputGroupAddon,
|
||||
Label
|
||||
} from "reactstrap";
|
||||
import { isPositiveNumber, isValidHostname, isValidIpv4 } from "../../validate";
|
||||
|
||||
class DHCPInfo extends Component {
|
||||
state = {
|
||||
active: "---",
|
||||
ip_start: "---",
|
||||
ip_end: "---",
|
||||
router_ip: "---",
|
||||
lease_time: "---",
|
||||
domain: "---",
|
||||
ipv6_support: "---"
|
||||
active: false,
|
||||
ip_start: "",
|
||||
ip_end: "",
|
||||
router_ip: "",
|
||||
lease_time: 24,
|
||||
domain: "",
|
||||
ipv6_support: false
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
@@ -45,18 +56,7 @@ class DHCPInfo extends Component {
|
||||
ipv6_support: res.ipv6_support
|
||||
});
|
||||
})
|
||||
.catch(ignoreCancel)
|
||||
.catch(() => {
|
||||
this.setState({
|
||||
active: "-!-",
|
||||
ip_start: "-!-",
|
||||
ip_end: "-!-",
|
||||
router_ip: "-!-",
|
||||
lease_time: "-!-",
|
||||
domain: "-!-",
|
||||
ipv6_support: "-!-"
|
||||
});
|
||||
});
|
||||
.catch(ignoreCancel);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
@@ -67,25 +67,151 @@ class DHCPInfo extends Component {
|
||||
this.updateHandler.cancel();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a function which will update the key in the state with the value
|
||||
* of the event attribute.
|
||||
*
|
||||
* @param key {string} the state to update
|
||||
* @param attr {string} the event target attribute to use
|
||||
* @returns {function(Event)}
|
||||
*/
|
||||
onChange = (key, attr) => {
|
||||
return e =>
|
||||
this.setState({
|
||||
[key]: e.target[attr]
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Save changes to DHCP settings
|
||||
*
|
||||
* @param e the submit event
|
||||
*/
|
||||
saveSettings = e => {
|
||||
e.preventDefault();
|
||||
|
||||
// TODO: send settings to API
|
||||
};
|
||||
|
||||
render() {
|
||||
const { t } = this.props;
|
||||
|
||||
const isIpStartValid = isValidIpv4(this.state.ip_start);
|
||||
const isIpEndValid = isValidIpv4(this.state.ip_end);
|
||||
const isRouterIpValid = isValidIpv4(this.state.router_ip);
|
||||
const isLeaseTimeValid = isPositiveNumber(this.state.lease_time);
|
||||
const isDomainValid = isValidHostname(this.state.domain);
|
||||
|
||||
return (
|
||||
<pre>
|
||||
{t("DHCP Active")}: {this.state.active.toString()}
|
||||
<br />
|
||||
{t("Start IP")}: {this.state.ip_start}
|
||||
<br />
|
||||
{t("End IP")}: {this.state.ip_end}
|
||||
<br />
|
||||
{t("Router IP")}: {this.state.router_ip}
|
||||
<br />
|
||||
{t("Lease Time")}: {this.state.lease_time} h<br />
|
||||
{t("Domain")}: {this.state.domain}
|
||||
<br />
|
||||
{t("IPv6 Support")}: {this.state.ipv6_support.toString()}
|
||||
<br />
|
||||
</pre>
|
||||
<Form onSubmit={this.saveSettings}>
|
||||
<FormGroup check>
|
||||
<Label check>
|
||||
<Input
|
||||
type="checkbox"
|
||||
checked={this.state.active}
|
||||
onChange={this.onChange("active", "checked")}
|
||||
/>
|
||||
{t("Enabled")}
|
||||
</Label>
|
||||
</FormGroup>
|
||||
<FormGroup row>
|
||||
<Label for="startIP" sm={2}>
|
||||
{t("Start IP")}
|
||||
</Label>
|
||||
<Col sm={10}>
|
||||
<Input
|
||||
id="startIP"
|
||||
disabled={!this.state.active}
|
||||
value={this.state.ip_start}
|
||||
onChange={this.onChange("ip_start", "value")}
|
||||
invalid={this.state.active && !isIpStartValid}
|
||||
/>
|
||||
</Col>
|
||||
</FormGroup>
|
||||
<FormGroup row>
|
||||
<Label for="endIP" sm={2}>
|
||||
{t("End IP")}
|
||||
</Label>
|
||||
<Col sm={10}>
|
||||
<Input
|
||||
id="endIP"
|
||||
disabled={!this.state.active}
|
||||
value={this.state.ip_end}
|
||||
onChange={this.onChange("ip_end", "value")}
|
||||
invalid={this.state.active && !isIpEndValid}
|
||||
/>
|
||||
</Col>
|
||||
</FormGroup>
|
||||
<FormGroup row>
|
||||
<Label for="routerIP" sm={2}>
|
||||
{t("Router IP")}
|
||||
</Label>
|
||||
<Col sm={10}>
|
||||
<Input
|
||||
id="routerIP"
|
||||
disabled={!this.state.active}
|
||||
value={this.state.router_ip}
|
||||
onChange={this.onChange("router_ip", "value")}
|
||||
invalid={this.state.active && !isRouterIpValid}
|
||||
/>
|
||||
</Col>
|
||||
</FormGroup>
|
||||
<FormGroup row>
|
||||
<Label for="leaseTime" sm={2}>
|
||||
{t("Lease Time")}
|
||||
</Label>
|
||||
<Col sm={10}>
|
||||
<InputGroup>
|
||||
<Input
|
||||
id="leaseTime"
|
||||
disabled={!this.state.active}
|
||||
value={this.state.lease_time}
|
||||
onChange={this.onChange("lease_time", "value")}
|
||||
invalid={this.state.active && !isLeaseTimeValid}
|
||||
/>
|
||||
<InputGroupAddon addonType={"append"}>Hours</InputGroupAddon>
|
||||
</InputGroup>
|
||||
</Col>
|
||||
</FormGroup>
|
||||
<FormGroup row>
|
||||
<Label for="domain" sm={2}>
|
||||
{t("Domain")}
|
||||
</Label>
|
||||
<Col sm={10}>
|
||||
<Input
|
||||
id="domain"
|
||||
disabled={!this.state.active}
|
||||
value={this.state.domain}
|
||||
onChange={this.onChange("domain", "value")}
|
||||
invalid={this.state.active && !isDomainValid}
|
||||
/>
|
||||
</Col>
|
||||
</FormGroup>
|
||||
<FormGroup check>
|
||||
<Label check>
|
||||
<Input
|
||||
type="checkbox"
|
||||
disabled={!this.state.active}
|
||||
checked={this.state.ipv6_support}
|
||||
onChange={this.onChange("ipv6_support", "checked")}
|
||||
/>
|
||||
{t("IPv6 Support")}
|
||||
</Label>
|
||||
</FormGroup>
|
||||
<Button
|
||||
type="submit"
|
||||
disabled={
|
||||
this.state.active &&
|
||||
(!isIpStartValid ||
|
||||
!isIpEndValid ||
|
||||
!isRouterIpValid ||
|
||||
!isLeaseTimeValid ||
|
||||
!isDomainValid)
|
||||
}
|
||||
>
|
||||
{t("Apply")}
|
||||
</Button>
|
||||
</Form>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,17 +14,17 @@ import { api, ignoreCancel, makeCancelable } from "../../utils";
|
||||
|
||||
class DNSInfo extends Component {
|
||||
state = {
|
||||
upstream_dns: ["---"],
|
||||
upstream_dns: [],
|
||||
conditional_forwarding: {
|
||||
enabled: "---",
|
||||
router_ip: "---",
|
||||
domain: "---"
|
||||
enabled: false,
|
||||
router_ip: "",
|
||||
domain: ""
|
||||
},
|
||||
options: {
|
||||
fqdn_required: "---",
|
||||
bogus_priv: "---",
|
||||
dnssec: "---",
|
||||
listening_type: "---"
|
||||
fqdn_required: false,
|
||||
bogus_priv: false,
|
||||
dnssec: false,
|
||||
listening_type: "single"
|
||||
}
|
||||
};
|
||||
|
||||
@@ -42,23 +42,7 @@ class DNSInfo extends Component {
|
||||
.then(res => {
|
||||
this.setState(res);
|
||||
})
|
||||
.catch(ignoreCancel)
|
||||
.catch(() => {
|
||||
this.setState({
|
||||
upstream_dns: ["-!-"],
|
||||
options: {
|
||||
fqdn_required: "-!-",
|
||||
bogus_priv: "-!-",
|
||||
dnssec: "-!-",
|
||||
listening_type: "-!-"
|
||||
},
|
||||
conditional_forwarding: {
|
||||
enabled: "-!-",
|
||||
router_ip: "-!-",
|
||||
domain: "-!-"
|
||||
}
|
||||
});
|
||||
});
|
||||
.catch(ignoreCancel);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
|
||||
@@ -14,9 +14,9 @@ import { api, ignoreCancel, makeCancelable } from "../../utils";
|
||||
|
||||
class FTLInfo extends Component {
|
||||
state = {
|
||||
filesize: "---",
|
||||
queries: "---",
|
||||
sqlite_version: "---"
|
||||
filesize: 0,
|
||||
queries: 0,
|
||||
sqlite_version: ""
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
@@ -37,14 +37,7 @@ class FTLInfo extends Component {
|
||||
sqlite_version: res.sqlite_version
|
||||
});
|
||||
})
|
||||
.catch(ignoreCancel)
|
||||
.catch(() => {
|
||||
this.setState({
|
||||
queries: "-!-",
|
||||
filesize: "-!-",
|
||||
sqlite_version: "-!-"
|
||||
});
|
||||
});
|
||||
.catch(ignoreCancel);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
|
||||
@@ -8,17 +8,17 @@
|
||||
* This file is copyright under the latest version of the EUPL.
|
||||
* Please see LICENSE file for your rights under this license. */
|
||||
|
||||
import React, { Component, Fragment } from "react";
|
||||
import React, { Component } from "react";
|
||||
import { translate } from "react-i18next";
|
||||
import { api, ignoreCancel, makeCancelable } from "../../utils";
|
||||
import { Col, Form, FormGroup, Input, Label } from "reactstrap";
|
||||
|
||||
class NetworkInfo extends Component {
|
||||
state = {
|
||||
interface: "---",
|
||||
ipv4_address: "---",
|
||||
ipv6_address: "---",
|
||||
hostname: "---"
|
||||
interface: "",
|
||||
ipv4_address: "",
|
||||
ipv6_address: "",
|
||||
hostname: ""
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
@@ -40,15 +40,7 @@ class NetworkInfo extends Component {
|
||||
hostname: res.hostname
|
||||
});
|
||||
})
|
||||
.catch(ignoreCancel)
|
||||
.catch(() => {
|
||||
this.setState({
|
||||
interface: "-!-",
|
||||
ipv4_address: "-!-",
|
||||
ipv6_address: "-!-",
|
||||
hostname: "-!-"
|
||||
});
|
||||
});
|
||||
.catch(ignoreCancel);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
@@ -63,50 +55,48 @@ class NetworkInfo extends Component {
|
||||
const { t } = this.props;
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<Form>
|
||||
<FormGroup row>
|
||||
<Label className="bold" for="interface" sm={4}>
|
||||
{t("Interface")}
|
||||
</Label>
|
||||
<Col sm={8}>
|
||||
<Input plaintext id="interface">
|
||||
{this.state.interface}
|
||||
</Input>
|
||||
</Col>
|
||||
</FormGroup>
|
||||
<FormGroup row>
|
||||
<Label className="bold" for="ipv4_address" sm={4}>
|
||||
{t("IPv4 address")}
|
||||
</Label>
|
||||
<Col sm={8}>
|
||||
<Input plaintext id="ipv4_address">
|
||||
{this.state.ipv4_address}
|
||||
</Input>
|
||||
</Col>
|
||||
</FormGroup>
|
||||
<FormGroup row>
|
||||
<Label className="bold" for="ipv6_address" sm={4}>
|
||||
{t("IPv6 address")}
|
||||
</Label>
|
||||
<Col sm={8}>
|
||||
<Input plaintext id="ipv6_address">
|
||||
{this.state.ipv6_address}
|
||||
</Input>
|
||||
</Col>
|
||||
</FormGroup>
|
||||
<FormGroup row>
|
||||
<Label className="bold" for="hostname" sm={4}>
|
||||
{t("Hostname")}
|
||||
</Label>
|
||||
<Col sm={8}>
|
||||
<Input plaintext id="hostname">
|
||||
{this.state.hostname}
|
||||
</Input>
|
||||
</Col>
|
||||
</FormGroup>
|
||||
</Form>
|
||||
</Fragment>
|
||||
<Form>
|
||||
<FormGroup row>
|
||||
<Label className="bold" for="interface" sm={4}>
|
||||
{t("Interface")}
|
||||
</Label>
|
||||
<Col sm={8}>
|
||||
<Input plaintext id="interface">
|
||||
{this.state.interface}
|
||||
</Input>
|
||||
</Col>
|
||||
</FormGroup>
|
||||
<FormGroup row>
|
||||
<Label className="bold" for="ipv4_address" sm={4}>
|
||||
{t("IPv4 address")}
|
||||
</Label>
|
||||
<Col sm={8}>
|
||||
<Input plaintext id="ipv4_address">
|
||||
{this.state.ipv4_address}
|
||||
</Input>
|
||||
</Col>
|
||||
</FormGroup>
|
||||
<FormGroup row>
|
||||
<Label className="bold" for="ipv6_address" sm={4}>
|
||||
{t("IPv6 address")}
|
||||
</Label>
|
||||
<Col sm={8}>
|
||||
<Input plaintext id="ipv6_address">
|
||||
{this.state.ipv6_address}
|
||||
</Input>
|
||||
</Col>
|
||||
</FormGroup>
|
||||
<FormGroup row>
|
||||
<Label className="bold" for="hostname" sm={4}>
|
||||
{t("Hostname")}
|
||||
</Label>
|
||||
<Col sm={8}>
|
||||
<Input plaintext id="hostname">
|
||||
{this.state.hostname}
|
||||
</Input>
|
||||
</Col>
|
||||
</FormGroup>
|
||||
</Form>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,24 +16,24 @@ import VersionCard from "./VersionCard";
|
||||
class VersionInfo extends Component {
|
||||
state = {
|
||||
api: {
|
||||
branch: "---",
|
||||
hash: "---",
|
||||
tag: "---"
|
||||
branch: "unknown",
|
||||
hash: "unknown",
|
||||
tag: "unknown"
|
||||
},
|
||||
core: {
|
||||
branch: "---",
|
||||
hash: "---",
|
||||
tag: "---"
|
||||
branch: "unknown",
|
||||
hash: "unknown",
|
||||
tag: "unknown"
|
||||
},
|
||||
ftl: {
|
||||
branch: "---",
|
||||
hash: "---",
|
||||
tag: "---"
|
||||
branch: "unknown",
|
||||
hash: "unknown",
|
||||
tag: "unknown"
|
||||
},
|
||||
web: {
|
||||
branch: "---",
|
||||
hash: "---",
|
||||
tag: "---"
|
||||
branch: "unknown",
|
||||
hash: "unknown",
|
||||
tag: "unknown"
|
||||
}
|
||||
};
|
||||
|
||||
@@ -51,31 +51,7 @@ class VersionInfo extends Component {
|
||||
.then(res => {
|
||||
this.setState(res);
|
||||
})
|
||||
.catch(ignoreCancel)
|
||||
.catch(() => {
|
||||
this.setState({
|
||||
api: {
|
||||
branch: "-!-",
|
||||
hash: "-!-",
|
||||
tag: "-!-"
|
||||
},
|
||||
core: {
|
||||
branch: "-!-",
|
||||
hash: "-!-",
|
||||
tag: "-!-"
|
||||
},
|
||||
ftl: {
|
||||
branch: "-!-",
|
||||
hash: "-!-",
|
||||
tag: "-!-"
|
||||
},
|
||||
web: {
|
||||
branch: "-!-",
|
||||
hash: "-!-",
|
||||
tag: "-!-"
|
||||
}
|
||||
});
|
||||
});
|
||||
.catch(ignoreCancel);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
|
||||
@@ -178,3 +178,7 @@
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.form-check-label {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
+25
-3
@@ -21,7 +21,7 @@ export function isValidHostname(hostname) {
|
||||
// Must not be all numbers and periods
|
||||
const joined = segments.join("");
|
||||
// If the hostname without periods make a number, deny
|
||||
if (isStrictNumeric(joined)) return false;
|
||||
if (isPositiveNumber(joined)) return false;
|
||||
|
||||
return /^([a-zA-Z0-9]+(-[a-zA-Z0-9]+)*)+(\.([a-zA-Z0-9]+(-[a-zA-Z0-9]+)*))*$/.test(
|
||||
hostname
|
||||
@@ -36,10 +36,10 @@ export function isValidDomain(domain) {
|
||||
return isValidHostname(domain);
|
||||
}
|
||||
|
||||
export function isStrictNumeric(input) {
|
||||
export function isPositiveNumber(input) {
|
||||
// Because parseInt has limitations, e.g. parseInt("15ex") is parsed to 15
|
||||
// Caution, does not work with negative numbers, replace with /^(\-|\+)?([0-9])$/ if needed
|
||||
return /^[0-9]*$/.test(input);
|
||||
return /^[0-9]+$/.test(input);
|
||||
}
|
||||
|
||||
export function isValidRegex(regex) {
|
||||
@@ -50,3 +50,25 @@ export function isValidRegex(regex) {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the string is a valid IPv4 address
|
||||
*
|
||||
* @param address {string} the address to check
|
||||
* @returns {boolean} if the address is a valid IPv4 address
|
||||
*/
|
||||
export function isValidIpv4(address) {
|
||||
const segments = address.split(".");
|
||||
|
||||
// Must have 4 segments
|
||||
if (segments.length !== 4) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// No segment can be longer than 3 characters or be empty
|
||||
|
||||
// All segments must be numbers (positive)
|
||||
return segments.every(
|
||||
segment => isPositiveNumber(segment) && parseInt(segment) < 256
|
||||
);
|
||||
}
|
||||
|
||||
+53
-5
@@ -8,7 +8,12 @@
|
||||
* This file is copyright under the latest version of the EUPL.
|
||||
* Please see LICENSE file for your rights under this license. */
|
||||
|
||||
import { isStrictNumeric, isValidDomain, isValidRegex } from "./validate";
|
||||
import {
|
||||
isPositiveNumber,
|
||||
isValidDomain,
|
||||
isValidIpv4,
|
||||
isValidRegex
|
||||
} from "./validate";
|
||||
|
||||
describe("Testing the validation functions", () => {
|
||||
describe("isValidDomain", () => {
|
||||
@@ -102,19 +107,24 @@ describe("Testing the validation functions", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("isStrictNumeric", () => {
|
||||
describe("isPositiveNumber", () => {
|
||||
it("passes 1234567890", () => {
|
||||
const result = isStrictNumeric("1234567890");
|
||||
const result = isPositiveNumber("1234567890");
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it("fails 1234a567890", () => {
|
||||
const result = isStrictNumeric("1234a567890");
|
||||
const result = isPositiveNumber("1234a567890");
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it("fails 1100101O1", () => {
|
||||
const result = isStrictNumeric("1100101O1");
|
||||
const result = isPositiveNumber("1100101O1");
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it("fails empty string", () => {
|
||||
const result = isPositiveNumber("");
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
});
|
||||
@@ -140,4 +150,42 @@ describe("Testing the validation functions", () => {
|
||||
expect(isValidRegex("[0-")).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("isValidIpv4", () => {
|
||||
it("passes 127.0.0.1", () => {
|
||||
expect(isValidIpv4("127.0.0.1")).toBe(true);
|
||||
});
|
||||
|
||||
it("passes 1.1.1.1", () => {
|
||||
expect(isValidIpv4("1.1.1.1")).toBe(true);
|
||||
});
|
||||
|
||||
it("passes 111.111.111.111", () => {
|
||||
expect(isValidIpv4("111.111.111.111")).toBe(true);
|
||||
});
|
||||
|
||||
it("fails 1111.1.1.1", () => {
|
||||
expect(isValidIpv4("1111.1.1.1")).toBe(false);
|
||||
});
|
||||
|
||||
it("fails 1.1.1.", () => {
|
||||
expect(isValidIpv4("1.1.1.")).toBe(false);
|
||||
});
|
||||
|
||||
it("fails empty string", () => {
|
||||
expect(isValidIpv4("")).toBe(false);
|
||||
});
|
||||
|
||||
it("fails 8.8", () => {
|
||||
expect(isValidIpv4("8.8")).toBe(false);
|
||||
});
|
||||
|
||||
it("fails 10. 10.1.1", () => {
|
||||
expect(isValidIpv4("10. 10.1.1")).toBe(false);
|
||||
});
|
||||
|
||||
it("fails 555.666.777.888", () => {
|
||||
expect(isValidIpv4("555.666.777.888")).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user