* client: installation wizard additional checks
This commit is contained in:
parent
9e68a522cb
commit
f76b7c3d94
@ -257,5 +257,7 @@
|
|||||||
"reset_settings": "Reset settings",
|
"reset_settings": "Reset settings",
|
||||||
"update_announcement": "AdGuard Home {{version}} is now available! <0>Click here<\/0> for more info.",
|
"update_announcement": "AdGuard Home {{version}} is now available! <0>Click here<\/0> for more info.",
|
||||||
"setup_guide": "Setup guide",
|
"setup_guide": "Setup guide",
|
||||||
"dns_addresses": "DNS addresses"
|
"dns_addresses": "DNS addresses",
|
||||||
|
"down": "Down",
|
||||||
|
"fix": "Fix"
|
||||||
}
|
}
|
@ -44,3 +44,18 @@ export const setAllSettings = values => async (dispatch) => {
|
|||||||
dispatch(prevStep());
|
dispatch(prevStep());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const checkConfigRequest = createAction('CHECK_CONFIG_REQUEST');
|
||||||
|
export const checkConfigFailure = createAction('CHECK_CONFIG_FAILURE');
|
||||||
|
export const checkConfigSuccess = createAction('CHECK_CONFIG_SUCCESS');
|
||||||
|
|
||||||
|
export const checkConfig = values => async (dispatch) => {
|
||||||
|
dispatch(checkConfigRequest());
|
||||||
|
try {
|
||||||
|
const check = await apiClient.checkConfig(values);
|
||||||
|
dispatch(checkConfigSuccess(check));
|
||||||
|
} catch (error) {
|
||||||
|
dispatch(addErrorToast({ error }));
|
||||||
|
dispatch(checkConfigFailure());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
@ -350,6 +350,7 @@ export default class Api {
|
|||||||
// Installation
|
// Installation
|
||||||
INSTALL_GET_ADDRESSES = { path: 'install/get_addresses', method: 'GET' };
|
INSTALL_GET_ADDRESSES = { path: 'install/get_addresses', method: 'GET' };
|
||||||
INSTALL_CONFIGURE = { path: 'install/configure', method: 'POST' };
|
INSTALL_CONFIGURE = { path: 'install/configure', method: 'POST' };
|
||||||
|
INSTALL_CHECK_CONFIG = { path: 'install/check_config', method: 'POST' };
|
||||||
|
|
||||||
getDefaultAddresses() {
|
getDefaultAddresses() {
|
||||||
const { path, method } = this.INSTALL_GET_ADDRESSES;
|
const { path, method } = this.INSTALL_GET_ADDRESSES;
|
||||||
@ -365,6 +366,15 @@ export default class Api {
|
|||||||
return this.makeRequest(path, method, parameters);
|
return this.makeRequest(path, method, parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
checkConfig(config) {
|
||||||
|
const { path, method } = this.INSTALL_CHECK_CONFIG;
|
||||||
|
const parameters = {
|
||||||
|
data: config,
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
};
|
||||||
|
return this.makeRequest(path, method, parameters);
|
||||||
|
}
|
||||||
|
|
||||||
// DNS-over-HTTPS and DNS-over-TLS
|
// DNS-over-HTTPS and DNS-over-TLS
|
||||||
TLS_STATUS = { path: 'tls/status', method: 'GET' };
|
TLS_STATUS = { path: 'tls/status', method: 'GET' };
|
||||||
TLS_CONFIG = { path: 'tls/configure', method: 'POST' };
|
TLS_CONFIG = { path: 'tls/configure', method: 'POST' };
|
||||||
|
@ -55,6 +55,8 @@ class Controls extends Component {
|
|||||||
invalid
|
invalid
|
||||||
|| pristine
|
|| pristine
|
||||||
|| install.processingSubmit
|
|| install.processingSubmit
|
||||||
|
|| install.dns.status
|
||||||
|
|| install.web.status
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<Trans>next</Trans>
|
<Trans>next</Trans>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import React from 'react';
|
import React, { Fragment } from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { Field, reduxForm, formValueSelector } from 'redux-form';
|
import { Field, reduxForm, formValueSelector } from 'redux-form';
|
||||||
@ -30,10 +30,25 @@ const toNumber = value => value && parseInt(value, 10);
|
|||||||
const renderInterfaces = (interfaces => (
|
const renderInterfaces = (interfaces => (
|
||||||
Object.keys(interfaces).map((item) => {
|
Object.keys(interfaces).map((item) => {
|
||||||
const option = interfaces[item];
|
const option = interfaces[item];
|
||||||
const { name } = option;
|
const {
|
||||||
|
name,
|
||||||
|
ip_addresses,
|
||||||
|
flags,
|
||||||
|
} = option;
|
||||||
|
|
||||||
if (option.ip_addresses && option.ip_addresses.length > 0) {
|
if (option && ip_addresses && ip_addresses.length > 0) {
|
||||||
const ip = getInterfaceIp(option);
|
const ip = getInterfaceIp(option);
|
||||||
|
const isDown = flags && flags.includes('down');
|
||||||
|
|
||||||
|
if (isDown) {
|
||||||
|
return (
|
||||||
|
<option value={ip} key={name} disabled>
|
||||||
|
<Fragment>
|
||||||
|
{name} - {ip} (<Trans>down</Trans>)
|
||||||
|
</Fragment>
|
||||||
|
</option>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<option value={ip} key={name}>
|
<option value={ip} key={name}>
|
||||||
@ -49,15 +64,24 @@ const renderInterfaces = (interfaces => (
|
|||||||
let Settings = (props) => {
|
let Settings = (props) => {
|
||||||
const {
|
const {
|
||||||
handleSubmit,
|
handleSubmit,
|
||||||
|
handleChange,
|
||||||
|
handleAutofix,
|
||||||
webIp,
|
webIp,
|
||||||
webPort,
|
webPort,
|
||||||
dnsIp,
|
dnsIp,
|
||||||
dnsPort,
|
dnsPort,
|
||||||
interfaces,
|
interfaces,
|
||||||
invalid,
|
invalid,
|
||||||
webWarning,
|
config,
|
||||||
dnsWarning,
|
|
||||||
} = props;
|
} = props;
|
||||||
|
const {
|
||||||
|
status: webStatus,
|
||||||
|
can_autofix: isWebFixAvailable,
|
||||||
|
} = config.web;
|
||||||
|
const {
|
||||||
|
status: dnsStatus,
|
||||||
|
can_autofix: isDnsFixAvailable,
|
||||||
|
} = config.dns;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form className="setup__step" onSubmit={handleSubmit}>
|
<form className="setup__step" onSubmit={handleSubmit}>
|
||||||
@ -75,6 +99,7 @@ let Settings = (props) => {
|
|||||||
name="web.ip"
|
name="web.ip"
|
||||||
component="select"
|
component="select"
|
||||||
className="form-control custom-select"
|
className="form-control custom-select"
|
||||||
|
onChange={handleChange}
|
||||||
>
|
>
|
||||||
<option value={ALL_INTERFACES_IP}>
|
<option value={ALL_INTERFACES_IP}>
|
||||||
<Trans>install_settings_all_interfaces</Trans>
|
<Trans>install_settings_all_interfaces</Trans>
|
||||||
@ -96,9 +121,26 @@ let Settings = (props) => {
|
|||||||
placeholder="80"
|
placeholder="80"
|
||||||
validate={[port, required]}
|
validate={[port, required]}
|
||||||
normalize={toNumber}
|
normalize={toNumber}
|
||||||
|
onChange={handleChange}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="col-12">
|
||||||
|
{webStatus &&
|
||||||
|
<div className="setup__error text-danger">
|
||||||
|
{webStatus}
|
||||||
|
{isWebFixAvailable &&
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="btn btn-secondary btn-sm ml-2"
|
||||||
|
onClick={() => handleAutofix('web', webIp, webPort)}
|
||||||
|
>
|
||||||
|
<Trans>fix</Trans>
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="setup__desc">
|
<div className="setup__desc">
|
||||||
<Trans>install_settings_interface_link</Trans>
|
<Trans>install_settings_interface_link</Trans>
|
||||||
@ -109,11 +151,6 @@ let Settings = (props) => {
|
|||||||
port={webPort}
|
port={webPort}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{webWarning &&
|
|
||||||
<div className="text-danger mt-2">
|
|
||||||
{webWarning}
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="setup__group">
|
<div className="setup__group">
|
||||||
@ -130,6 +167,7 @@ let Settings = (props) => {
|
|||||||
name="dns.ip"
|
name="dns.ip"
|
||||||
component="select"
|
component="select"
|
||||||
className="form-control custom-select"
|
className="form-control custom-select"
|
||||||
|
onChange={handleChange}
|
||||||
>
|
>
|
||||||
<option value={ALL_INTERFACES_IP}>
|
<option value={ALL_INTERFACES_IP}>
|
||||||
<Trans>install_settings_all_interfaces</Trans>
|
<Trans>install_settings_all_interfaces</Trans>
|
||||||
@ -151,9 +189,26 @@ let Settings = (props) => {
|
|||||||
placeholder="80"
|
placeholder="80"
|
||||||
validate={[port, required]}
|
validate={[port, required]}
|
||||||
normalize={toNumber}
|
normalize={toNumber}
|
||||||
|
onChange={handleChange}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="col-12">
|
||||||
|
{dnsStatus &&
|
||||||
|
<div className="setup__error text-danger">
|
||||||
|
{dnsStatus}
|
||||||
|
{isDnsFixAvailable &&
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="btn btn-secondary btn-sm ml-2"
|
||||||
|
onClick={() => handleAutofix('dns', dnsIp, dnsPort)}
|
||||||
|
>
|
||||||
|
<Trans>fix</Trans>
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="setup__desc">
|
<div className="setup__desc">
|
||||||
<Trans>install_settings_dns_desc</Trans>
|
<Trans>install_settings_dns_desc</Trans>
|
||||||
@ -165,11 +220,6 @@ let Settings = (props) => {
|
|||||||
isDns={true}
|
isDns={true}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{dnsWarning &&
|
|
||||||
<div className="text-danger mt-2">
|
|
||||||
{dnsWarning}
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Controls invalid={invalid} />
|
<Controls invalid={invalid} />
|
||||||
@ -179,8 +229,11 @@ let Settings = (props) => {
|
|||||||
|
|
||||||
Settings.propTypes = {
|
Settings.propTypes = {
|
||||||
handleSubmit: PropTypes.func.isRequired,
|
handleSubmit: PropTypes.func.isRequired,
|
||||||
|
handleChange: PropTypes.func,
|
||||||
|
handleAutofix: PropTypes.func,
|
||||||
webIp: PropTypes.string.isRequired,
|
webIp: PropTypes.string.isRequired,
|
||||||
dnsIp: PropTypes.string.isRequired,
|
dnsIp: PropTypes.string.isRequired,
|
||||||
|
config: PropTypes.object.isRequired,
|
||||||
webPort: PropTypes.oneOfType([
|
webPort: PropTypes.oneOfType([
|
||||||
PropTypes.string,
|
PropTypes.string,
|
||||||
PropTypes.number,
|
PropTypes.number,
|
||||||
@ -189,8 +242,6 @@ Settings.propTypes = {
|
|||||||
PropTypes.string,
|
PropTypes.string,
|
||||||
PropTypes.number,
|
PropTypes.number,
|
||||||
]),
|
]),
|
||||||
webWarning: PropTypes.string.isRequired,
|
|
||||||
dnsWarning: PropTypes.string.isRequired,
|
|
||||||
interfaces: PropTypes.object.isRequired,
|
interfaces: PropTypes.object.isRequired,
|
||||||
invalid: PropTypes.bool.isRequired,
|
invalid: PropTypes.bool.isRequired,
|
||||||
initialValues: PropTypes.object,
|
initialValues: PropTypes.object,
|
||||||
|
@ -115,3 +115,7 @@
|
|||||||
padding-left: 30px;
|
padding-left: 30px;
|
||||||
padding-right: 30px;
|
padding-right: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.setup__error {
|
||||||
|
margin: -5px 0 5px;
|
||||||
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import React, { Component, Fragment } from 'react';
|
import React, { Component, Fragment } from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
import debounce from 'lodash/debounce';
|
||||||
|
|
||||||
import * as actionCreators from '../../actions/install';
|
import * as actionCreators from '../../actions/install';
|
||||||
import { getWebAddress } from '../../helpers/helpers';
|
import { getWebAddress } from '../../helpers/helpers';
|
||||||
@ -8,6 +9,7 @@ import {
|
|||||||
INSTALL_FIRST_STEP,
|
INSTALL_FIRST_STEP,
|
||||||
INSTALL_TOTAL_STEPS,
|
INSTALL_TOTAL_STEPS,
|
||||||
ALL_INTERFACES_IP,
|
ALL_INTERFACES_IP,
|
||||||
|
DEBOUNCE_TIMEOUT,
|
||||||
} from '../../helpers/constants';
|
} from '../../helpers/constants';
|
||||||
|
|
||||||
import Loading from '../../components/ui/Loading';
|
import Loading from '../../components/ui/Loading';
|
||||||
@ -34,6 +36,30 @@ class Setup extends Component {
|
|||||||
this.props.setAllSettings(values);
|
this.props.setAllSettings(values);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
handleFormChange = debounce((values) => {
|
||||||
|
if (values && values.web.port && values.dns.port) {
|
||||||
|
this.props.checkConfig(values);
|
||||||
|
}
|
||||||
|
}, DEBOUNCE_TIMEOUT);
|
||||||
|
|
||||||
|
handleAutofix = (type, ip, port) => {
|
||||||
|
const data = {
|
||||||
|
ip,
|
||||||
|
port,
|
||||||
|
autofix: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (type === 'web') {
|
||||||
|
this.props.checkConfig({
|
||||||
|
web: { ...data },
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.props.checkConfig({
|
||||||
|
dns: { ...data },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
openDashboard = (ip, port) => {
|
openDashboard = (ip, port) => {
|
||||||
let address = getWebAddress(ip, port);
|
let address = getWebAddress(ip, port);
|
||||||
|
|
||||||
@ -63,11 +89,12 @@ class Setup extends Component {
|
|||||||
case 2:
|
case 2:
|
||||||
return (
|
return (
|
||||||
<Settings
|
<Settings
|
||||||
|
config={config}
|
||||||
initialValues={config}
|
initialValues={config}
|
||||||
interfaces={interfaces}
|
interfaces={interfaces}
|
||||||
webWarning={config.web.warning}
|
|
||||||
dnsWarning={config.dns.warning}
|
|
||||||
onSubmit={this.nextStep}
|
onSubmit={this.nextStep}
|
||||||
|
onChange={this.handleFormChange}
|
||||||
|
handleAutofix={this.handleAutofix}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
case 3:
|
case 3:
|
||||||
@ -116,6 +143,7 @@ class Setup extends Component {
|
|||||||
Setup.propTypes = {
|
Setup.propTypes = {
|
||||||
getDefaultAddresses: PropTypes.func.isRequired,
|
getDefaultAddresses: PropTypes.func.isRequired,
|
||||||
setAllSettings: PropTypes.func.isRequired,
|
setAllSettings: PropTypes.func.isRequired,
|
||||||
|
checkConfig: PropTypes.func.isRequired,
|
||||||
nextStep: PropTypes.func.isRequired,
|
nextStep: PropTypes.func.isRequired,
|
||||||
prevStep: PropTypes.func.isRequired,
|
prevStep: PropTypes.func.isRequired,
|
||||||
install: PropTypes.object.isRequired,
|
install: PropTypes.object.isRequired,
|
||||||
|
@ -10,10 +10,13 @@ const install = handleActions({
|
|||||||
[actions.getDefaultAddressesRequest]: state => ({ ...state, processingDefault: true }),
|
[actions.getDefaultAddressesRequest]: state => ({ ...state, processingDefault: true }),
|
||||||
[actions.getDefaultAddressesFailure]: state => ({ ...state, processingDefault: false }),
|
[actions.getDefaultAddressesFailure]: state => ({ ...state, processingDefault: false }),
|
||||||
[actions.getDefaultAddressesSuccess]: (state, { payload }) => {
|
[actions.getDefaultAddressesSuccess]: (state, { payload }) => {
|
||||||
const values = payload;
|
const { interfaces } = payload;
|
||||||
values.web.ip = state.web.ip;
|
const web = { ...state.web, ...payload.web };
|
||||||
values.dns.ip = state.dns.ip;
|
const dns = { ...state.dns, ...payload.dns };
|
||||||
const newState = { ...state, ...values, processingDefault: false };
|
|
||||||
|
const newState = {
|
||||||
|
...state, web, dns, interfaces, processingDefault: false,
|
||||||
|
};
|
||||||
return newState;
|
return newState;
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -23,19 +26,34 @@ const install = handleActions({
|
|||||||
[actions.setAllSettingsRequest]: state => ({ ...state, processingSubmit: true }),
|
[actions.setAllSettingsRequest]: state => ({ ...state, processingSubmit: true }),
|
||||||
[actions.setAllSettingsFailure]: state => ({ ...state, processingSubmit: false }),
|
[actions.setAllSettingsFailure]: state => ({ ...state, processingSubmit: false }),
|
||||||
[actions.setAllSettingsSuccess]: state => ({ ...state, processingSubmit: false }),
|
[actions.setAllSettingsSuccess]: state => ({ ...state, processingSubmit: false }),
|
||||||
|
|
||||||
|
[actions.checkConfigRequest]: state => ({ ...state, processingCheck: true }),
|
||||||
|
[actions.checkConfigFailure]: state => ({ ...state, processingCheck: false }),
|
||||||
|
[actions.checkConfigSuccess]: (state, { payload }) => {
|
||||||
|
const web = { ...state.web, ...payload.web };
|
||||||
|
const dns = { ...state.dns, ...payload.dns };
|
||||||
|
|
||||||
|
const newState = {
|
||||||
|
...state, web, dns, processingCheck: false,
|
||||||
|
};
|
||||||
|
return newState;
|
||||||
|
},
|
||||||
}, {
|
}, {
|
||||||
step: INSTALL_FIRST_STEP,
|
step: INSTALL_FIRST_STEP,
|
||||||
processingDefault: true,
|
processingDefault: true,
|
||||||
processingSubmit: false,
|
processingSubmit: false,
|
||||||
|
processingCheck: false,
|
||||||
web: {
|
web: {
|
||||||
ip: '0.0.0.0',
|
ip: '0.0.0.0',
|
||||||
port: 80,
|
port: 80,
|
||||||
warning: '',
|
status: '',
|
||||||
|
can_autofix: false,
|
||||||
},
|
},
|
||||||
dns: {
|
dns: {
|
||||||
ip: '0.0.0.0',
|
ip: '0.0.0.0',
|
||||||
port: 53,
|
port: 53,
|
||||||
warning: '',
|
status: '',
|
||||||
|
can_autofix: false,
|
||||||
},
|
},
|
||||||
interfaces: {},
|
interfaces: {},
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user