- client: Fix client Access settings normalization
Close #1820 Squashed commit of the following: commit 5aadec2e6e126588313ff006d6f95223ba19a526 Merge: a4db6b4295f41285
Author: ArtemBaskal <a.baskal@adguard.com> Date: Wed Jul 15 11:15:31 2020 +0300 Merge branch 'master' into fix/1820 commit a4db6b42ab9cbf43d96c783a72a99e0a2c594108 Author: ArtemBaskal <a.baskal@adguard.com> Date: Tue Jul 14 19:08:09 2020 +0300 Remove textarea comma splitting commit bb34797aac6602b405941dbd90fe6a81b663bb92 Author: ArtemBaskal <a.baskal@adguard.com> Date: Tue Jul 14 18:21:18 2020 +0300 Fix client Access settings normalization commit ac4fb536514f54c5722077d78dbbd981c4e906a8 Merge: 0c758ddcb9fca8d0
Author: ArtemBaskal <a.baskal@adguard.com> Date: Tue Jul 14 18:14:38 2020 +0300 Merge branch 'master' into fix/1820 commit 0c758ddcd738136b92e6f947a8068ecc59f7ec25 Merge: 15650db3f5a1f311
Author: ArtemBaskal <a.baskal@adguard.com> Date: Fri Jul 3 11:22:00 2020 +0300 Merge branch 'master' into fix/1820 commit 15650db35323009001fd427a74a312705b54ac86 Author: ArtemBaskal <a.baskal@adguard.com> Date: Mon Jun 29 12:01:51 2020 +0300 '- client: Don't normalise disallowed domains'
This commit is contained in:
parent
95f4128551
commit
a32c1f2ee0
|
@ -2,9 +2,9 @@ import { createAction } from 'redux-actions';
|
||||||
import i18next from 'i18next';
|
import i18next from 'i18next';
|
||||||
|
|
||||||
import apiClient from '../api/Api';
|
import apiClient from '../api/Api';
|
||||||
import { normalizeTextarea } from '../helpers/helpers';
|
|
||||||
import { addErrorToast, addSuccessToast } from './toasts';
|
import { addErrorToast, addSuccessToast } from './toasts';
|
||||||
import { BLOCK_ACTIONS } from '../helpers/constants';
|
import { BLOCK_ACTIONS } from '../helpers/constants';
|
||||||
|
import { splitByNewLine } from '../helpers/helpers';
|
||||||
|
|
||||||
export const getAccessListRequest = createAction('GET_ACCESS_LIST_REQUEST');
|
export const getAccessListRequest = createAction('GET_ACCESS_LIST_REQUEST');
|
||||||
export const getAccessListFailure = createAction('GET_ACCESS_LIST_FAILURE');
|
export const getAccessListFailure = createAction('GET_ACCESS_LIST_FAILURE');
|
||||||
|
@ -31,9 +31,9 @@ export const setAccessList = (config) => async (dispatch) => {
|
||||||
const { allowed_clients, disallowed_clients, blocked_hosts } = config;
|
const { allowed_clients, disallowed_clients, blocked_hosts } = config;
|
||||||
|
|
||||||
const values = {
|
const values = {
|
||||||
allowed_clients: normalizeTextarea(allowed_clients),
|
allowed_clients: splitByNewLine(allowed_clients),
|
||||||
disallowed_clients: normalizeTextarea(disallowed_clients),
|
disallowed_clients: splitByNewLine(disallowed_clients),
|
||||||
blocked_hosts: normalizeTextarea(blocked_hosts),
|
blocked_hosts: splitByNewLine(blocked_hosts),
|
||||||
};
|
};
|
||||||
|
|
||||||
await apiClient.setAccessList(values);
|
await apiClient.setAccessList(values);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { createAction } from 'redux-actions';
|
import { createAction } from 'redux-actions';
|
||||||
|
|
||||||
import apiClient from '../api/Api';
|
import apiClient from '../api/Api';
|
||||||
import { normalizeTextarea } from '../helpers/helpers';
|
import { splitByNewLine } from '../helpers/helpers';
|
||||||
import { addErrorToast, addSuccessToast } from './toasts';
|
import { addErrorToast, addSuccessToast } from './toasts';
|
||||||
|
|
||||||
export const getDnsConfigRequest = createAction('GET_DNS_CONFIG_REQUEST');
|
export const getDnsConfigRequest = createAction('GET_DNS_CONFIG_REQUEST');
|
||||||
|
@ -30,11 +30,11 @@ export const setDnsConfig = (config) => async (dispatch) => {
|
||||||
|
|
||||||
let hasDnsSettings = false;
|
let hasDnsSettings = false;
|
||||||
if (Object.prototype.hasOwnProperty.call(data, 'bootstrap_dns')) {
|
if (Object.prototype.hasOwnProperty.call(data, 'bootstrap_dns')) {
|
||||||
data.bootstrap_dns = normalizeTextarea(config.bootstrap_dns);
|
data.bootstrap_dns = splitByNewLine(config.bootstrap_dns);
|
||||||
hasDnsSettings = true;
|
hasDnsSettings = true;
|
||||||
}
|
}
|
||||||
if (Object.prototype.hasOwnProperty.call(data, 'upstream_dns')) {
|
if (Object.prototype.hasOwnProperty.call(data, 'upstream_dns')) {
|
||||||
data.upstream_dns = normalizeTextarea(config.upstream_dns);
|
data.upstream_dns = splitByNewLine(config.upstream_dns);
|
||||||
hasDnsSettings = true;
|
hasDnsSettings = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { createAction } from 'redux-actions';
|
||||||
import i18next from 'i18next';
|
import i18next from 'i18next';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
|
||||||
import { isVersionGreater, normalizeTextarea, sortClients } from '../helpers/helpers';
|
import { isVersionGreater, splitByNewLine, sortClients } from '../helpers/helpers';
|
||||||
import { CHECK_TIMEOUT, SETTINGS_NAMES } from '../helpers/constants';
|
import { CHECK_TIMEOUT, SETTINGS_NAMES } from '../helpers/constants';
|
||||||
import { getTlsStatus } from './encryption';
|
import { getTlsStatus } from './encryption';
|
||||||
import apiClient from '../api/Api';
|
import apiClient from '../api/Api';
|
||||||
|
@ -279,8 +279,8 @@ export const testUpstream = (config) => async (dispatch) => {
|
||||||
dispatch(testUpstreamRequest());
|
dispatch(testUpstreamRequest());
|
||||||
try {
|
try {
|
||||||
const values = { ...config };
|
const values = { ...config };
|
||||||
values.bootstrap_dns = normalizeTextarea(values.bootstrap_dns);
|
values.bootstrap_dns = splitByNewLine(values.bootstrap_dns);
|
||||||
values.upstream_dns = normalizeTextarea(values.upstream_dns);
|
values.upstream_dns = splitByNewLine(values.upstream_dns);
|
||||||
|
|
||||||
const upstreamResponse = await apiClient.testUpstream(values);
|
const upstreamResponse = await apiClient.testUpstream(values);
|
||||||
const testMessages = Object.keys(upstreamResponse)
|
const testMessages = Object.keys(upstreamResponse)
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { Trans, withTranslation } from 'react-i18next';
|
||||||
import ReactTable from 'react-table';
|
import ReactTable from 'react-table';
|
||||||
|
|
||||||
import { MODAL_TYPE } from '../../../helpers/constants';
|
import { MODAL_TYPE } from '../../../helpers/constants';
|
||||||
import { normalizeTextarea } from '../../../helpers/helpers';
|
import { splitByNewLine } from '../../../helpers/helpers';
|
||||||
import Card from '../../ui/Card';
|
import Card from '../../ui/Card';
|
||||||
import Modal from './Modal';
|
import Modal from './Modal';
|
||||||
import CellWrap from '../../ui/CellWrap';
|
import CellWrap from '../../ui/CellWrap';
|
||||||
|
@ -30,7 +30,7 @@ class ClientsTable extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (values.upstreams && typeof values.upstreams === 'string') {
|
if (values.upstreams && typeof values.upstreams === 'string') {
|
||||||
config.upstreams = normalizeTextarea(values.upstreams);
|
config.upstreams = splitByNewLine(values.upstreams);
|
||||||
} else {
|
} else {
|
||||||
config.upstreams = [];
|
config.upstreams = [];
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,10 @@ import { Field, reduxForm } from 'redux-form';
|
||||||
import { Trans, withTranslation } from 'react-i18next';
|
import { Trans, withTranslation } from 'react-i18next';
|
||||||
import flow from 'lodash/flow';
|
import flow from 'lodash/flow';
|
||||||
import { renderTextareaField } from '../../../../helpers/form';
|
import { renderTextareaField } from '../../../../helpers/form';
|
||||||
import { normalizeMultiline } from '../../../../helpers/helpers';
|
import {
|
||||||
|
trimMultilineString,
|
||||||
|
removeEmptyLines,
|
||||||
|
} from '../../../../helpers/helpers';
|
||||||
import { FORM_NAME } from '../../../../helpers/constants';
|
import { FORM_NAME } from '../../../../helpers/constants';
|
||||||
|
|
||||||
const fields = [
|
const fields = [
|
||||||
|
@ -12,16 +15,19 @@ const fields = [
|
||||||
id: 'allowed_clients',
|
id: 'allowed_clients',
|
||||||
title: 'access_allowed_title',
|
title: 'access_allowed_title',
|
||||||
subtitle: 'access_allowed_desc',
|
subtitle: 'access_allowed_desc',
|
||||||
|
normalizeOnBlur: removeEmptyLines,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'disallowed_clients',
|
id: 'disallowed_clients',
|
||||||
title: 'access_disallowed_title',
|
title: 'access_disallowed_title',
|
||||||
subtitle: 'access_disallowed_desc',
|
subtitle: 'access_disallowed_desc',
|
||||||
|
normalizeOnBlur: trimMultilineString,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'blocked_hosts',
|
id: 'blocked_hosts',
|
||||||
title: 'access_blocked_title',
|
title: 'access_blocked_title',
|
||||||
subtitle: 'access_blocked_desc',
|
subtitle: 'access_blocked_desc',
|
||||||
|
normalizeOnBlur: removeEmptyLines,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -31,7 +37,7 @@ const Form = (props) => {
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const renderField = ({
|
const renderField = ({
|
||||||
id, title, subtitle, disabled = processingSet,
|
id, title, subtitle, disabled = processingSet, normalizeOnBlur,
|
||||||
}) => <div key={id} className="form__group mb-5">
|
}) => <div key={id} className="form__group mb-5">
|
||||||
<label className="form__label form__label--with-desc" htmlFor={id}>
|
<label className="form__label form__label--with-desc" htmlFor={id}>
|
||||||
<Trans>{title}</Trans>
|
<Trans>{title}</Trans>
|
||||||
|
@ -46,7 +52,7 @@ const Form = (props) => {
|
||||||
type="text"
|
type="text"
|
||||||
className="form-control form-control--textarea font-monospace"
|
className="form-control form-control--textarea font-monospace"
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
normalizeOnBlur={id === 'disallowed_clients' ? normalizeMultiline : undefined}
|
normalizeOnBlur={normalizeOnBlur}
|
||||||
/>
|
/>
|
||||||
</div>;
|
</div>;
|
||||||
|
|
||||||
|
@ -55,6 +61,7 @@ const Form = (props) => {
|
||||||
title: PropTypes.string,
|
title: PropTypes.string,
|
||||||
subtitle: PropTypes.string,
|
subtitle: PropTypes.string,
|
||||||
disabled: PropTypes.bool,
|
disabled: PropTypes.bool,
|
||||||
|
normalizeOnBlur: PropTypes.func,
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -6,9 +6,10 @@ import { Trans, useTranslation } from 'react-i18next';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
|
|
||||||
import Examples from './Examples';
|
import Examples from './Examples';
|
||||||
import { renderRadioField } from '../../../../helpers/form';
|
import { renderRadioField, renderTextareaField } from '../../../../helpers/form';
|
||||||
import { DNS_REQUEST_OPTIONS, FORM_NAME } from '../../../../helpers/constants';
|
import { DNS_REQUEST_OPTIONS, FORM_NAME } from '../../../../helpers/constants';
|
||||||
import { testUpstream } from '../../../../actions';
|
import { testUpstream } from '../../../../actions';
|
||||||
|
import { removeEmptyLines } from '../../../../helpers/helpers';
|
||||||
|
|
||||||
const getInputFields = () => [{
|
const getInputFields = () => [{
|
||||||
// eslint-disable-next-line react/display-name
|
// eslint-disable-next-line react/display-name
|
||||||
|
@ -17,9 +18,10 @@ const getInputFields = () => [{
|
||||||
</label>,
|
</label>,
|
||||||
name: 'upstream_dns',
|
name: 'upstream_dns',
|
||||||
type: 'text',
|
type: 'text',
|
||||||
component: 'textarea',
|
component: renderTextareaField,
|
||||||
className: 'form-control form-control--textarea font-monospace',
|
className: 'form-control form-control--textarea font-monospace',
|
||||||
placeholder: 'upstream_dns',
|
placeholder: 'upstream_dns',
|
||||||
|
normalizeOnBlur: removeEmptyLines,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'upstream_mode',
|
name: 'upstream_mode',
|
||||||
|
@ -69,7 +71,8 @@ const Form = ({
|
||||||
return <form onSubmit={handleSubmit}>
|
return <form onSubmit={handleSubmit}>
|
||||||
<div className="row">
|
<div className="row">
|
||||||
{INPUT_FIELDS.map(({
|
{INPUT_FIELDS.map(({
|
||||||
name, component, type, className, placeholder, getTitle, subtitle, disabled, value,
|
name, component, type, className, placeholder,
|
||||||
|
getTitle, subtitle, disabled, value, normalizeOnBlur,
|
||||||
}) => <div className="col-12 mb-4" key={placeholder}>
|
}) => <div className="col-12 mb-4" key={placeholder}>
|
||||||
{typeof getTitle === 'function' && getTitle()}
|
{typeof getTitle === 'function' && getTitle()}
|
||||||
<Field
|
<Field
|
||||||
|
@ -82,6 +85,7 @@ const Form = ({
|
||||||
placeholder={t(placeholder)}
|
placeholder={t(placeholder)}
|
||||||
subtitle={t(subtitle)}
|
subtitle={t(subtitle)}
|
||||||
disabled={processingSetConfig || processingTestUpstream || disabled}
|
disabled={processingSetConfig || processingTestUpstream || disabled}
|
||||||
|
normalizeOnBlur={normalizeOnBlur}
|
||||||
/>
|
/>
|
||||||
</div>)}
|
</div>)}
|
||||||
<div className="col-12">
|
<div className="col-12">
|
||||||
|
@ -101,11 +105,12 @@ const Form = ({
|
||||||
<Field
|
<Field
|
||||||
id="bootstrap_dns"
|
id="bootstrap_dns"
|
||||||
name="bootstrap_dns"
|
name="bootstrap_dns"
|
||||||
component="textarea"
|
component={renderTextareaField}
|
||||||
type="text"
|
type="text"
|
||||||
className="form-control form-control--textarea form-control--textarea-small font-monospace"
|
className="form-control form-control--textarea form-control--textarea-small font-monospace"
|
||||||
placeholder={t('bootstrap_dns')}
|
placeholder={t('bootstrap_dns')}
|
||||||
disabled={processingSetConfig}
|
disabled={processingSetConfig}
|
||||||
|
normalizeOnBlur={removeEmptyLines}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -45,7 +45,10 @@ const Dns = (props) => {
|
||||||
dnsConfig={dnsConfig}
|
dnsConfig={dnsConfig}
|
||||||
setDnsConfig={setDnsConfig}
|
setDnsConfig={setDnsConfig}
|
||||||
/>
|
/>
|
||||||
<Access access={access} setAccessList={setAccessList} />
|
<Access
|
||||||
|
access={access}
|
||||||
|
setAccessList={setAccessList}
|
||||||
|
/>
|
||||||
</>}
|
</>}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
@ -306,15 +306,26 @@ export const redirectToCurrentProtocol = (values, httpPort = 80) => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const normalizeTextarea = (text) => {
|
/**
|
||||||
if (!text) {
|
* @param {string} text
|
||||||
return [];
|
* @returns []string
|
||||||
}
|
*/
|
||||||
|
export const splitByNewLine = (text) => text.split('\n')
|
||||||
|
.filter((n) => n.trim());
|
||||||
|
|
||||||
return text.replace(/[;, ]/g, '\n')
|
/**
|
||||||
.split('\n')
|
* @param {string} text
|
||||||
.filter((n) => n);
|
* @returns {string}
|
||||||
};
|
*/
|
||||||
|
export const trimMultilineString = (text) => splitByNewLine(text)
|
||||||
|
.map((line) => line.trim()).join('\n');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} text
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
export const removeEmptyLines = (text) => splitByNewLine(text)
|
||||||
|
.join('\n');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Normalizes the topClients array
|
* Normalizes the topClients array
|
||||||
|
@ -533,10 +544,6 @@ export const getMap = (arr, key, value) => arr.reduce((acc, curr) => {
|
||||||
return acc;
|
return acc;
|
||||||
}, {});
|
}, {});
|
||||||
|
|
||||||
export const normalizeMultiline = (multiline) => `${normalizeTextarea(multiline)
|
|
||||||
.map((line) => line.trim())
|
|
||||||
.join('\n')}\n`;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param parsedIp {object} ipaddr.js IPv4 or IPv6 object
|
* @param parsedIp {object} ipaddr.js IPv4 or IPv6 object
|
||||||
* @param cidr {array} ipaddr.js CIDR array
|
* @param cidr {array} ipaddr.js CIDR array
|
||||||
|
|
Loading…
Reference in New Issue