+ client: handle DNS config
This commit is contained in:
parent
87bb773d3e
commit
197d07f32b
|
@ -187,6 +187,15 @@
|
||||||
"query_log_disabled": "The query log is disabled and can be configured in the <0>settings</0>",
|
"query_log_disabled": "The query log is disabled and can be configured in the <0>settings</0>",
|
||||||
"query_log_strict_search": "Use double quotes for strict search",
|
"query_log_strict_search": "Use double quotes for strict search",
|
||||||
"query_log_retention_confirm": "Are you sure you want to change query log retention? If you decrease the interval value, some data will be lost",
|
"query_log_retention_confirm": "Are you sure you want to change query log retention? If you decrease the interval value, some data will be lost",
|
||||||
|
"dns_config": "DNS configuration",
|
||||||
|
"blocking_mode": "Blocking mode",
|
||||||
|
"nxdomain": "NXDOMAIN",
|
||||||
|
"null_ip": "Null IP",
|
||||||
|
"custom_ip": "Custom IP",
|
||||||
|
"blocking_ipv4": "Blocking IPv4",
|
||||||
|
"blocking_ipv6": "Blocking IPv6",
|
||||||
|
"form_enter_rate_limit": "Enter rate limit",
|
||||||
|
"rate_limit": "Rate limit",
|
||||||
"source_label": "Source",
|
"source_label": "Source",
|
||||||
"found_in_known_domain_db": "Found in the known domains database.",
|
"found_in_known_domain_db": "Found in the known domains database.",
|
||||||
"category_label": "Category",
|
"category_label": "Category",
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
import { createAction } from 'redux-actions';
|
||||||
|
|
||||||
|
import apiClient from '../api/Api';
|
||||||
|
import { addErrorToast, addSuccessToast } from './index';
|
||||||
|
|
||||||
|
export const getDnsConfigRequest = createAction('GET_DNS_CONFIG_REQUEST');
|
||||||
|
export const getDnsConfigFailure = createAction('GET_DNS_CONFIG_FAILURE');
|
||||||
|
export const getDnsConfigSuccess = createAction('GET_DNS_CONFIG_SUCCESS');
|
||||||
|
|
||||||
|
export const getDnsConfig = () => async (dispatch) => {
|
||||||
|
dispatch(getDnsConfigRequest());
|
||||||
|
try {
|
||||||
|
const data = await apiClient.getDnsConfig();
|
||||||
|
dispatch(getDnsConfigSuccess(data));
|
||||||
|
} catch (error) {
|
||||||
|
dispatch(addErrorToast({ error }));
|
||||||
|
dispatch(getDnsConfigFailure());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const setDnsConfigRequest = createAction('SET_DNS_CONFIG_REQUEST');
|
||||||
|
export const setDnsConfigFailure = createAction('SET_DNS_CONFIG_FAILURE');
|
||||||
|
export const setDnsConfigSuccess = createAction('SET_DNS_CONFIG_SUCCESS');
|
||||||
|
|
||||||
|
export const setDnsConfig = config => async (dispatch) => {
|
||||||
|
dispatch(setDnsConfigRequest());
|
||||||
|
try {
|
||||||
|
await apiClient.setDnsConfig(config);
|
||||||
|
dispatch(addSuccessToast('config_successfully_saved'));
|
||||||
|
dispatch(setDnsConfigSuccess(config));
|
||||||
|
} catch (error) {
|
||||||
|
dispatch(addErrorToast({ error }));
|
||||||
|
dispatch(setDnsConfigFailure());
|
||||||
|
}
|
||||||
|
};
|
|
@ -91,17 +91,9 @@ export const toggleProtectionSuccess = createAction('TOGGLE_PROTECTION_SUCCESS')
|
||||||
|
|
||||||
export const toggleProtection = status => async (dispatch) => {
|
export const toggleProtection = status => async (dispatch) => {
|
||||||
dispatch(toggleProtectionRequest());
|
dispatch(toggleProtectionRequest());
|
||||||
let successMessage = '';
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (status) {
|
const successMessage = status ? 'disabled_protection' : 'enabled_protection';
|
||||||
successMessage = 'disabled_protection';
|
await apiClient.setDnsConfig({ protection_enabled: !status });
|
||||||
await apiClient.disableGlobalProtection();
|
|
||||||
} else {
|
|
||||||
successMessage = 'enabled_protection';
|
|
||||||
await apiClient.enableGlobalProtection();
|
|
||||||
}
|
|
||||||
|
|
||||||
dispatch(addSuccessToast(successMessage));
|
dispatch(addSuccessToast(successMessage));
|
||||||
dispatch(toggleProtectionSuccess());
|
dispatch(toggleProtectionSuccess());
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
|
@ -30,8 +30,6 @@ class Api {
|
||||||
GLOBAL_SET_UPSTREAM_DNS = { path: 'set_upstreams_config', method: 'POST' };
|
GLOBAL_SET_UPSTREAM_DNS = { path: 'set_upstreams_config', method: 'POST' };
|
||||||
GLOBAL_TEST_UPSTREAM_DNS = { path: 'test_upstream_dns', method: 'POST' };
|
GLOBAL_TEST_UPSTREAM_DNS = { path: 'test_upstream_dns', method: 'POST' };
|
||||||
GLOBAL_VERSION = { path: 'version.json', method: 'POST' };
|
GLOBAL_VERSION = { path: 'version.json', method: 'POST' };
|
||||||
GLOBAL_ENABLE_PROTECTION = { path: 'enable_protection', method: 'POST' };
|
|
||||||
GLOBAL_DISABLE_PROTECTION = { path: 'disable_protection', method: 'POST' };
|
|
||||||
GLOBAL_UPDATE = { path: 'update', method: 'POST' };
|
GLOBAL_UPDATE = { path: 'update', method: 'POST' };
|
||||||
|
|
||||||
startGlobalFiltering() {
|
startGlobalFiltering() {
|
||||||
|
@ -76,16 +74,6 @@ class Api {
|
||||||
return this.makeRequest(path, method, config);
|
return this.makeRequest(path, method, config);
|
||||||
}
|
}
|
||||||
|
|
||||||
enableGlobalProtection() {
|
|
||||||
const { path, method } = this.GLOBAL_ENABLE_PROTECTION;
|
|
||||||
return this.makeRequest(path, method);
|
|
||||||
}
|
|
||||||
|
|
||||||
disableGlobalProtection() {
|
|
||||||
const { path, method } = this.GLOBAL_DISABLE_PROTECTION;
|
|
||||||
return this.makeRequest(path, method);
|
|
||||||
}
|
|
||||||
|
|
||||||
getUpdate() {
|
getUpdate() {
|
||||||
const { path, method } = this.GLOBAL_UPDATE;
|
const { path, method } = this.GLOBAL_UPDATE;
|
||||||
return this.makeRequest(path, method);
|
return this.makeRequest(path, method);
|
||||||
|
@ -546,6 +534,24 @@ class Api {
|
||||||
const { path, method } = this.GET_PROFILE;
|
const { path, method } = this.GET_PROFILE;
|
||||||
return this.makeRequest(path, method);
|
return this.makeRequest(path, method);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DNS config
|
||||||
|
GET_DNS_CONFIG = { path: 'dns_info', method: 'GET' };
|
||||||
|
SET_DNS_CONFIG = { path: 'dns_config', method: 'POST' };
|
||||||
|
|
||||||
|
getDnsConfig() {
|
||||||
|
const { path, method } = this.GET_DNS_CONFIG;
|
||||||
|
return this.makeRequest(path, method);
|
||||||
|
}
|
||||||
|
|
||||||
|
setDnsConfig(data) {
|
||||||
|
const { path, method } = this.SET_DNS_CONFIG;
|
||||||
|
const config = {
|
||||||
|
data,
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
};
|
||||||
|
return this.makeRequest(path, method, config);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const apiClient = new Api();
|
const apiClient = new Api();
|
||||||
|
|
|
@ -0,0 +1,120 @@
|
||||||
|
import React, { Fragment } from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import { Field, reduxForm, formValueSelector } from 'redux-form';
|
||||||
|
import { Trans, withNamespaces } from 'react-i18next';
|
||||||
|
import flow from 'lodash/flow';
|
||||||
|
|
||||||
|
import { renderField, renderRadioField, required, ipv4, ipv6, isPositive, toNumber } from '../../../helpers/form';
|
||||||
|
import { BLOCKING_MODES } from '../../../helpers/constants';
|
||||||
|
|
||||||
|
const getFields = (processing, t) => Object.values(BLOCKING_MODES).map(mode => (
|
||||||
|
<Field
|
||||||
|
key={mode}
|
||||||
|
name="blocking_mode"
|
||||||
|
type="radio"
|
||||||
|
component={renderRadioField}
|
||||||
|
value={mode}
|
||||||
|
placeholder={t(mode)}
|
||||||
|
disabled={processing}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
|
||||||
|
let Form = ({
|
||||||
|
handleSubmit, submitting, invalid, processing, blockingMode, t,
|
||||||
|
}) => (
|
||||||
|
<form onSubmit={handleSubmit}>
|
||||||
|
<div className="row">
|
||||||
|
<div className="col-12 col-sm-6">
|
||||||
|
<div className="form__group form__group--settings">
|
||||||
|
<label htmlFor="ratelimit">
|
||||||
|
<Trans>rate_limit</Trans>
|
||||||
|
</label>
|
||||||
|
<Field
|
||||||
|
name="ratelimit"
|
||||||
|
type="number"
|
||||||
|
component={renderField}
|
||||||
|
className="form-control"
|
||||||
|
placeholder={t('form_enter_rate_limit')}
|
||||||
|
normalize={toNumber}
|
||||||
|
validate={[required, isPositive]}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="col-12">
|
||||||
|
<div className="form__group form__group--settings mb-3">
|
||||||
|
<label className="form__label">
|
||||||
|
<Trans>blocking_mode</Trans>
|
||||||
|
</label>
|
||||||
|
<div className="custom-controls-stacked">
|
||||||
|
{getFields(processing, t)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{blockingMode === BLOCKING_MODES.custom_ip && (
|
||||||
|
<Fragment>
|
||||||
|
<div className="col-12 col-sm-6">
|
||||||
|
<div className="form__group form__group--settings">
|
||||||
|
<label htmlFor="blocking_ipv4">
|
||||||
|
<Trans>blocking_ipv4</Trans>
|
||||||
|
</label>
|
||||||
|
<Field
|
||||||
|
name="blocking_ipv4"
|
||||||
|
component={renderField}
|
||||||
|
className="form-control"
|
||||||
|
placeholder={t('form_enter_ip')}
|
||||||
|
validate={[ipv4, required]}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="col-12 col-sm-6">
|
||||||
|
<div className="form__group form__group--settings">
|
||||||
|
<label htmlFor="ip_address">
|
||||||
|
<Trans>blocking_ipv6</Trans>
|
||||||
|
</label>
|
||||||
|
<Field
|
||||||
|
name="blocking_ipv6"
|
||||||
|
component={renderField}
|
||||||
|
className="form-control"
|
||||||
|
placeholder={t('form_enter_ip')}
|
||||||
|
validate={[ipv6, required]}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Fragment>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
className="btn btn-success btn-standard btn-large"
|
||||||
|
disabled={submitting || invalid || processing}
|
||||||
|
>
|
||||||
|
<Trans>save_btn</Trans>
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
);
|
||||||
|
|
||||||
|
Form.propTypes = {
|
||||||
|
blockingMode: PropTypes.string.isRequired,
|
||||||
|
handleSubmit: PropTypes.func.isRequired,
|
||||||
|
submitting: PropTypes.bool.isRequired,
|
||||||
|
invalid: PropTypes.bool.isRequired,
|
||||||
|
processing: PropTypes.bool.isRequired,
|
||||||
|
t: PropTypes.func.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
const selector = formValueSelector('blockingModeForm');
|
||||||
|
|
||||||
|
Form = connect((state) => {
|
||||||
|
const blockingMode = selector(state, 'blocking_mode');
|
||||||
|
return {
|
||||||
|
blockingMode,
|
||||||
|
};
|
||||||
|
})(Form);
|
||||||
|
|
||||||
|
export default flow([
|
||||||
|
withNamespaces(),
|
||||||
|
reduxForm({
|
||||||
|
form: 'blockingModeForm',
|
||||||
|
}),
|
||||||
|
])(Form);
|
|
@ -0,0 +1,49 @@
|
||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { withNamespaces } from 'react-i18next';
|
||||||
|
|
||||||
|
import Card from '../../ui/Card';
|
||||||
|
import Form from './Form';
|
||||||
|
|
||||||
|
const DnsConfig = ({ t, dnsConfig, setDnsConfig }) => {
|
||||||
|
const handleFormSubmit = (values) => {
|
||||||
|
setDnsConfig(values);
|
||||||
|
};
|
||||||
|
|
||||||
|
const {
|
||||||
|
blocking_mode,
|
||||||
|
ratelimit,
|
||||||
|
blocking_ipv4,
|
||||||
|
blocking_ipv6,
|
||||||
|
processingSetConfig,
|
||||||
|
} = dnsConfig;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Card
|
||||||
|
title={t('dns_config')}
|
||||||
|
bodyType="card-body box-body--settings"
|
||||||
|
id="dns-config"
|
||||||
|
>
|
||||||
|
<div className="form">
|
||||||
|
<Form
|
||||||
|
initialValues={{
|
||||||
|
ratelimit,
|
||||||
|
blocking_mode,
|
||||||
|
blocking_ipv4,
|
||||||
|
blocking_ipv6,
|
||||||
|
}}
|
||||||
|
onSubmit={handleFormSubmit}
|
||||||
|
processing={processingSetConfig}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
DnsConfig.propTypes = {
|
||||||
|
dnsConfig: PropTypes.object.isRequired,
|
||||||
|
setDnsConfig: PropTypes.func.isRequired,
|
||||||
|
t: PropTypes.func.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default withNamespaces()(DnsConfig);
|
|
@ -6,6 +6,8 @@ import Services from './Services';
|
||||||
import StatsConfig from './StatsConfig';
|
import StatsConfig from './StatsConfig';
|
||||||
import LogsConfig from './LogsConfig';
|
import LogsConfig from './LogsConfig';
|
||||||
import FiltersConfig from './FiltersConfig';
|
import FiltersConfig from './FiltersConfig';
|
||||||
|
import DnsConfig from './DnsConfig';
|
||||||
|
|
||||||
import Checkbox from '../ui/Checkbox';
|
import Checkbox from '../ui/Checkbox';
|
||||||
import Loading from '../ui/Loading';
|
import Loading from '../ui/Loading';
|
||||||
import PageTitle from '../ui/PageTitle';
|
import PageTitle from '../ui/PageTitle';
|
||||||
|
@ -38,6 +40,7 @@ class Settings extends Component {
|
||||||
this.props.getStatsConfig();
|
this.props.getStatsConfig();
|
||||||
this.props.getLogsConfig();
|
this.props.getLogsConfig();
|
||||||
this.props.getFilteringStatus();
|
this.props.getFilteringStatus();
|
||||||
|
this.props.getDnsConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
renderSettings = (settings) => {
|
renderSettings = (settings) => {
|
||||||
|
@ -68,10 +71,12 @@ class Settings extends Component {
|
||||||
resetStats,
|
resetStats,
|
||||||
stats,
|
stats,
|
||||||
queryLogs,
|
queryLogs,
|
||||||
|
dnsConfig,
|
||||||
setLogsConfig,
|
setLogsConfig,
|
||||||
clearLogs,
|
clearLogs,
|
||||||
filtering,
|
filtering,
|
||||||
setFiltersConfig,
|
setFiltersConfig,
|
||||||
|
setDnsConfig,
|
||||||
t,
|
t,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
|
@ -101,6 +106,12 @@ class Settings extends Component {
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="col-md-12">
|
||||||
|
<DnsConfig
|
||||||
|
dnsConfig={dnsConfig}
|
||||||
|
setDnsConfig={setDnsConfig}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<div className="col-md-12">
|
<div className="col-md-12">
|
||||||
<LogsConfig
|
<LogsConfig
|
||||||
enabled={queryLogs.enabled}
|
enabled={queryLogs.enabled}
|
||||||
|
@ -143,6 +154,7 @@ Settings.propTypes = {
|
||||||
resetStats: PropTypes.func.isRequired,
|
resetStats: PropTypes.func.isRequired,
|
||||||
setFiltersConfig: PropTypes.func.isRequired,
|
setFiltersConfig: PropTypes.func.isRequired,
|
||||||
getFilteringStatus: PropTypes.func.isRequired,
|
getFilteringStatus: PropTypes.func.isRequired,
|
||||||
|
getDnsConfig: PropTypes.func.isRequired,
|
||||||
t: PropTypes.func.isRequired,
|
t: PropTypes.func.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -4,11 +4,12 @@ import { getBlockedServices, setBlockedServices } from '../actions/services';
|
||||||
import { getStatsConfig, setStatsConfig, resetStats } from '../actions/stats';
|
import { getStatsConfig, setStatsConfig, resetStats } from '../actions/stats';
|
||||||
import { clearLogs, getLogsConfig, setLogsConfig } from '../actions/queryLogs';
|
import { clearLogs, getLogsConfig, setLogsConfig } from '../actions/queryLogs';
|
||||||
import { getFilteringStatus, setFiltersConfig } from '../actions/filtering';
|
import { getFilteringStatus, setFiltersConfig } from '../actions/filtering';
|
||||||
|
import { getDnsConfig, setDnsConfig } from '../actions/dnsConfig';
|
||||||
import Settings from '../components/Settings';
|
import Settings from '../components/Settings';
|
||||||
|
|
||||||
const mapStateToProps = (state) => {
|
const mapStateToProps = (state) => {
|
||||||
const {
|
const {
|
||||||
settings, services, stats, queryLogs, filtering,
|
settings, services, stats, queryLogs, filtering, dnsConfig,
|
||||||
} = state;
|
} = state;
|
||||||
const props = {
|
const props = {
|
||||||
settings,
|
settings,
|
||||||
|
@ -16,6 +17,7 @@ const mapStateToProps = (state) => {
|
||||||
stats,
|
stats,
|
||||||
queryLogs,
|
queryLogs,
|
||||||
filtering,
|
filtering,
|
||||||
|
dnsConfig,
|
||||||
};
|
};
|
||||||
return props;
|
return props;
|
||||||
};
|
};
|
||||||
|
@ -33,6 +35,8 @@ const mapDispatchToProps = {
|
||||||
setLogsConfig,
|
setLogsConfig,
|
||||||
getFilteringStatus,
|
getFilteringStatus,
|
||||||
setFiltersConfig,
|
setFiltersConfig,
|
||||||
|
getDnsConfig,
|
||||||
|
setDnsConfig,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default connect(
|
export default connect(
|
||||||
|
|
|
@ -341,6 +341,12 @@ export const QUERY_LOG_INTERVALS_DAYS = [1, 7, 30, 90];
|
||||||
|
|
||||||
export const FILTERS_INTERVALS_HOURS = [0, 1, 12, 24, 72, 168];
|
export const FILTERS_INTERVALS_HOURS = [0, 1, 12, 24, 72, 168];
|
||||||
|
|
||||||
|
export const BLOCKING_MODES = {
|
||||||
|
nxdomain: 'nxdomain',
|
||||||
|
null_ip: 'null_ip',
|
||||||
|
custom_ip: 'custom_ip',
|
||||||
|
};
|
||||||
|
|
||||||
export const WHOIS_ICONS = {
|
export const WHOIS_ICONS = {
|
||||||
location: 'location',
|
location: 'location',
|
||||||
orgname: 'network',
|
orgname: 'network',
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
import { handleActions } from 'redux-actions';
|
||||||
|
|
||||||
|
import * as actions from '../actions/dnsConfig';
|
||||||
|
import { BLOCKING_MODES } from '../helpers/constants';
|
||||||
|
|
||||||
|
const dnsConfig = handleActions(
|
||||||
|
{
|
||||||
|
[actions.getDnsConfigRequest]: state => ({ ...state, processingGetConfig: true }),
|
||||||
|
[actions.getDnsConfigFailure]: state =>
|
||||||
|
({ ...state, processingGetConfig: false }),
|
||||||
|
[actions.getDnsConfigSuccess]: (state, { payload }) => ({
|
||||||
|
...state,
|
||||||
|
...payload,
|
||||||
|
processingGetConfig: false,
|
||||||
|
}),
|
||||||
|
|
||||||
|
[actions.setDnsConfigRequest]: state => ({ ...state, processingSetConfig: true }),
|
||||||
|
[actions.setDnsConfigFailure]: state =>
|
||||||
|
({ ...state, processingSetConfig: false }),
|
||||||
|
[actions.setDnsConfigSuccess]: (state, { payload }) => ({
|
||||||
|
...state,
|
||||||
|
...payload,
|
||||||
|
processingSetConfig: false,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
processingGetConfig: false,
|
||||||
|
processingSetConfig: false,
|
||||||
|
blocking_mode: BLOCKING_MODES.nxdomain,
|
||||||
|
ratelimit: 20,
|
||||||
|
blocking_ipv4: '',
|
||||||
|
blocking_ipv6: '',
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
export default dnsConfig;
|
|
@ -13,6 +13,7 @@ import rewrites from './rewrites';
|
||||||
import services from './services';
|
import services from './services';
|
||||||
import stats from './stats';
|
import stats from './stats';
|
||||||
import queryLogs from './queryLogs';
|
import queryLogs from './queryLogs';
|
||||||
|
import dnsConfig from './dnsConfig';
|
||||||
import filtering from './filtering';
|
import filtering from './filtering';
|
||||||
|
|
||||||
const settings = handleActions(
|
const settings = handleActions(
|
||||||
|
@ -369,6 +370,7 @@ export default combineReducers({
|
||||||
rewrites,
|
rewrites,
|
||||||
services,
|
services,
|
||||||
stats,
|
stats,
|
||||||
|
dnsConfig,
|
||||||
loadingBar: loadingBarReducer,
|
loadingBar: loadingBarReducer,
|
||||||
form: formReducer,
|
form: formReducer,
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue