+ client: handle check host
This commit is contained in:
parent
0d7c01d50f
commit
8ec7c37715
|
@ -446,5 +446,17 @@
|
|||
"autofix_warning_result": "As a result all DNS requests from your system will be processed by AdGuardHome by default.",
|
||||
"tags_title": "Tags",
|
||||
"tags_desc": "You can select the tags that correspond to the client. Tags can be included in the filtering rules and allow you to apply them more accurately. <0>Learn more</0>",
|
||||
"form_select_tags": "Select client tags"
|
||||
"form_select_tags": "Select client tags",
|
||||
"check_title": "Check the filtering",
|
||||
"check_desc": "Check if the host name is filtered",
|
||||
"check": "Check",
|
||||
"form_enter_host": "Enter a host name",
|
||||
"filtered_custom_rules": "Filtered by Custom filtering rules",
|
||||
"host_whitelisted": "The host is whitelisted",
|
||||
"check_ip": "IP addresses: {{ip}}",
|
||||
"check_cname": "CNAME: {{cname}}",
|
||||
"check_reason": "Reason: {{reason}}",
|
||||
"check_rule": "Rule: {{rule}}",
|
||||
"check_service": "Service name: {{service}}",
|
||||
"check_not_found": "Doesn't exist in any filter"
|
||||
}
|
||||
|
|
|
@ -161,3 +161,23 @@ export const setFiltersConfig = config => async (dispatch, getState) => {
|
|||
dispatch(setFiltersConfigFailure());
|
||||
}
|
||||
};
|
||||
|
||||
export const checkHostRequest = createAction('CHECK_HOST_REQUEST');
|
||||
export const checkHostFailure = createAction('CHECK_HOST_FAILURE');
|
||||
export const checkHostSuccess = createAction('CHECK_HOST_SUCCESS');
|
||||
|
||||
export const checkHost = host => async (dispatch) => {
|
||||
dispatch(checkHostRequest());
|
||||
try {
|
||||
const data = await apiClient.checkHost(host);
|
||||
const [hostname] = Object.values(host);
|
||||
|
||||
dispatch(checkHostSuccess({
|
||||
hostname,
|
||||
...data,
|
||||
}));
|
||||
} catch (error) {
|
||||
dispatch(addErrorToast({ error }));
|
||||
dispatch(checkHostFailure());
|
||||
}
|
||||
};
|
||||
|
|
|
@ -82,6 +82,7 @@ class Api {
|
|||
FILTERING_REFRESH = { path: 'filtering/refresh', method: 'POST' };
|
||||
FILTERING_SET_URL = { path: 'filtering/set_url', method: 'POST' };
|
||||
FILTERING_CONFIG = { path: 'filtering/config', method: 'POST' };
|
||||
FILTERING_CHECK_HOST = { path: 'filtering/check_host', method: 'GET' };
|
||||
|
||||
getFilteringStatus() {
|
||||
const { path, method } = this.FILTERING_STATUS;
|
||||
|
@ -141,6 +142,12 @@ class Api {
|
|||
return this.makeRequest(path, method, parameters);
|
||||
}
|
||||
|
||||
checkHost(params) {
|
||||
const { path, method } = this.FILTERING_CHECK_HOST;
|
||||
const url = getPathWithQueryString(path, params);
|
||||
return this.makeRequest(url, method);
|
||||
}
|
||||
|
||||
// Parental
|
||||
PARENTAL_STATUS = { path: 'parental/status', method: 'GET' };
|
||||
PARENTAL_ENABLE = { path: 'parental/enable', method: 'POST' };
|
||||
|
|
|
@ -0,0 +1,127 @@
|
|||
import React, { Fragment } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { withNamespaces } from 'react-i18next';
|
||||
|
||||
import { checkFiltered, checkRewrite, checkBlackList, checkNotFilteredNotFound, checkWhiteList } from '../../../helpers/helpers';
|
||||
|
||||
const getFilterName = (id, filters, t) => {
|
||||
if (id === 0) {
|
||||
return t('filtered_custom_rules');
|
||||
}
|
||||
|
||||
const filter = filters.find(filter => filter.id === id);
|
||||
|
||||
if (filter && filter.name) {
|
||||
return t('query_log_filtered', { filter: filter.name });
|
||||
}
|
||||
|
||||
return '';
|
||||
};
|
||||
|
||||
const getTitle = (reason, filterName, t) => {
|
||||
if (checkNotFilteredNotFound(reason)) {
|
||||
return t('check_not_found');
|
||||
}
|
||||
|
||||
if (checkRewrite(reason)) {
|
||||
return t('rewrite_applied');
|
||||
}
|
||||
|
||||
if (checkBlackList(reason)) {
|
||||
return filterName;
|
||||
}
|
||||
|
||||
if (checkWhiteList(reason)) {
|
||||
return (
|
||||
<Fragment>
|
||||
<div>
|
||||
{t('host_whitelisted')}
|
||||
</div>
|
||||
<div>
|
||||
{filterName}
|
||||
</div>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<div>
|
||||
{t('check_reason', { reason })}
|
||||
</div>
|
||||
<div>
|
||||
{filterName}
|
||||
</div>
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
const getColor = (reason) => {
|
||||
if (checkFiltered(reason)) {
|
||||
return 'red';
|
||||
} else if (checkRewrite(reason)) {
|
||||
return 'blue';
|
||||
} else if (checkWhiteList(reason)) {
|
||||
return 'green';
|
||||
}
|
||||
|
||||
return '';
|
||||
};
|
||||
|
||||
const Info = ({
|
||||
filters,
|
||||
hostname,
|
||||
reason,
|
||||
filter_id,
|
||||
rule,
|
||||
service_name,
|
||||
cname,
|
||||
ip_addrs,
|
||||
t,
|
||||
}) => {
|
||||
const filterName = getFilterName(filter_id, filters, t);
|
||||
const title = getTitle(reason, filterName, t);
|
||||
const color = getColor(reason);
|
||||
|
||||
return (
|
||||
<div className={`card mb-0 p-3 ${color}`}>
|
||||
<div>
|
||||
<strong>{hostname}</strong>
|
||||
</div>
|
||||
|
||||
<div>{title}</div>
|
||||
|
||||
{rule && (
|
||||
<div>{t('check_rule', { rule })}</div>
|
||||
)}
|
||||
|
||||
{service_name && (
|
||||
<div>{t('check_service', { service: service_name })}</div>
|
||||
)}
|
||||
|
||||
{cname && (
|
||||
<div>{t('check_cname', { cname })}</div>
|
||||
)}
|
||||
|
||||
{ip_addrs && (
|
||||
<div>
|
||||
{t('check_ip', { ip: ip_addrs.join(', ') })}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
Info.propTypes = {
|
||||
filters: PropTypes.array.isRequired,
|
||||
hostname: PropTypes.string.isRequired,
|
||||
reason: PropTypes.string.isRequired,
|
||||
filter_id: PropTypes.number,
|
||||
rule: PropTypes.string,
|
||||
service_name: PropTypes.string,
|
||||
cname: PropTypes.string,
|
||||
ip_addrs: PropTypes.array,
|
||||
t: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default withNamespaces()(Info);
|
|
@ -0,0 +1,95 @@
|
|||
import React, { Fragment } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Trans, withNamespaces } from 'react-i18next';
|
||||
import { Field, reduxForm } from 'redux-form';
|
||||
import flow from 'lodash/flow';
|
||||
import Card from '../../ui/Card';
|
||||
|
||||
import { renderInputField } from '../../../helpers/form';
|
||||
import Info from './Info';
|
||||
|
||||
const Check = (props) => {
|
||||
const {
|
||||
t,
|
||||
handleSubmit,
|
||||
pristine,
|
||||
invalid,
|
||||
processing,
|
||||
check,
|
||||
filters,
|
||||
} = props;
|
||||
|
||||
const {
|
||||
hostname,
|
||||
reason,
|
||||
filter_id,
|
||||
rule,
|
||||
service_name,
|
||||
cname,
|
||||
ip_addrs,
|
||||
} = check;
|
||||
|
||||
return (
|
||||
<Card
|
||||
title={t('check_title')}
|
||||
subtitle={t('check_desc')}
|
||||
>
|
||||
<form onSubmit={handleSubmit}>
|
||||
<div className="row">
|
||||
<div className="col-12 col-md-6">
|
||||
<div className="input-group">
|
||||
<Field
|
||||
id="name"
|
||||
name="name"
|
||||
component={renderInputField}
|
||||
type="text"
|
||||
className="form-control"
|
||||
placeholder={t('form_enter_host')}
|
||||
/>
|
||||
<span className="input-group-append">
|
||||
<button
|
||||
className="btn btn-success btn-standard btn-large"
|
||||
type="submit"
|
||||
onClick={this.handleSubmit}
|
||||
disabled={pristine || invalid || processing}
|
||||
>
|
||||
<Trans>check</Trans>
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
{check.hostname && (
|
||||
<Fragment>
|
||||
<hr/>
|
||||
<Info
|
||||
filters={filters}
|
||||
hostname={hostname}
|
||||
reason={reason}
|
||||
filter_id={filter_id}
|
||||
rule={rule}
|
||||
service_name={service_name}
|
||||
cname={cname}
|
||||
ip_addrs={ip_addrs}
|
||||
/>
|
||||
</Fragment>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
||||
Check.propTypes = {
|
||||
t: PropTypes.func.isRequired,
|
||||
handleSubmit: PropTypes.func.isRequired,
|
||||
pristine: PropTypes.bool.isRequired,
|
||||
invalid: PropTypes.bool.isRequired,
|
||||
processing: PropTypes.bool.isRequired,
|
||||
check: PropTypes.object.isRequired,
|
||||
filters: PropTypes.array.isRequired,
|
||||
};
|
||||
|
||||
export default flow([
|
||||
withNamespaces(),
|
||||
reduxForm({ form: 'domainCheckForm' }),
|
||||
])(Check);
|
|
@ -26,7 +26,7 @@ class UserRules extends Component {
|
|||
/>
|
||||
<div className="card-actions">
|
||||
<button
|
||||
className="btn btn-success btn-standard"
|
||||
className="btn btn-success btn-standard btn-large"
|
||||
type="submit"
|
||||
onClick={this.handleSubmit}
|
||||
>
|
||||
|
|
|
@ -8,8 +8,9 @@ import Card from '../ui/Card';
|
|||
import CellWrap from '../ui/CellWrap';
|
||||
import UserRules from './UserRules';
|
||||
import Modal from './Modal';
|
||||
import { formatDetailedDateTime } from '../../helpers/helpers';
|
||||
import Check from './Check';
|
||||
|
||||
import { formatDetailedDateTime } from '../../helpers/helpers';
|
||||
import { MODAL_TYPE } from '../../helpers/constants';
|
||||
|
||||
class Filters extends Component {
|
||||
|
@ -76,6 +77,10 @@ class Filters extends Component {
|
|||
return { name: '', url: '' };
|
||||
};
|
||||
|
||||
handleCheck = (values) => {
|
||||
this.props.checkHost(values);
|
||||
}
|
||||
|
||||
columns = [
|
||||
{
|
||||
Header: <Trans>enabled_table_header</Trans>,
|
||||
|
@ -180,6 +185,8 @@ class Filters extends Component {
|
|||
processingFilters,
|
||||
modalType,
|
||||
modalFilterUrl,
|
||||
processingCheck,
|
||||
check,
|
||||
} = filtering;
|
||||
|
||||
const currentFilterData = this.getFilter(modalFilterUrl, filters);
|
||||
|
@ -216,7 +223,7 @@ class Filters extends Component {
|
|||
/>
|
||||
<div className="card-actions">
|
||||
<button
|
||||
className="btn btn-success btn-standard mr-2"
|
||||
className="btn btn-success btn-standard mr-2 btn-large"
|
||||
type="submit"
|
||||
onClick={() =>
|
||||
toggleFilteringModal({ type: MODAL_TYPE.ADD })
|
||||
|
@ -242,6 +249,14 @@ class Filters extends Component {
|
|||
handleRulesSubmit={this.handleRulesSubmit}
|
||||
/>
|
||||
</div>
|
||||
<div className="col-md-12">
|
||||
<Check
|
||||
filters={filters}
|
||||
check={check}
|
||||
onSubmit={this.handleCheck}
|
||||
processing={processingCheck}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Modal
|
||||
|
@ -274,6 +289,7 @@ Filters.propTypes = {
|
|||
processingConfigFilter: PropTypes.bool.isRequired,
|
||||
processingRemoveFilter: PropTypes.bool.isRequired,
|
||||
modalType: PropTypes.string.isRequired,
|
||||
processingCheck: PropTypes.bool.isRequired,
|
||||
}),
|
||||
removeFilter: PropTypes.func.isRequired,
|
||||
toggleFilterStatus: PropTypes.func.isRequired,
|
||||
|
@ -282,6 +298,7 @@ Filters.propTypes = {
|
|||
handleRulesChange: PropTypes.func.isRequired,
|
||||
refreshFilters: PropTypes.func.isRequired,
|
||||
editFilter: PropTypes.func.isRequired,
|
||||
checkHost: PropTypes.func.isRequired,
|
||||
t: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
|
|
|
@ -112,3 +112,15 @@
|
|||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
.card .red {
|
||||
background-color: #fff4f2;
|
||||
}
|
||||
|
||||
.card .green {
|
||||
background-color: #f1faf3;
|
||||
}
|
||||
|
||||
.card .blue {
|
||||
background-color: #ecf7ff;
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import {
|
|||
refreshFilters,
|
||||
handleRulesChange,
|
||||
editFilter,
|
||||
checkHost,
|
||||
} from '../actions/filtering';
|
||||
import Filters from '../components/Filters';
|
||||
|
||||
|
@ -28,6 +29,7 @@ const mapDispatchToProps = {
|
|||
refreshFilters,
|
||||
handleRulesChange,
|
||||
editFilter,
|
||||
checkHost,
|
||||
};
|
||||
|
||||
export default connect(
|
||||
|
|
|
@ -349,10 +349,14 @@ export const ENCRYPTION_SOURCE = {
|
|||
export const FILTERED_STATUS = {
|
||||
FILTERED_BLACK_LIST: 'FilteredBlackList',
|
||||
NOT_FILTERED_WHITE_LIST: 'NotFilteredWhiteList',
|
||||
NOT_FILTERED_NOT_FOUND: 'NotFilteredNotFound',
|
||||
FILTERED_BLOCKED_SERVICE: 'FilteredBlockedService',
|
||||
REWRITE: 'Rewrite',
|
||||
};
|
||||
|
||||
export const FILTERED = 'Filtered';
|
||||
export const NOT_FILTERED = 'NotFiltered';
|
||||
|
||||
export const STATS_INTERVALS_DAYS = [1, 7, 30, 90];
|
||||
|
||||
export const QUERY_LOG_INTERVALS_DAYS = [1, 7, 30, 90];
|
||||
|
|
|
@ -22,6 +22,8 @@ import {
|
|||
DEFAULT_DATE_FORMAT_OPTIONS,
|
||||
DETAILED_DATE_FORMAT_OPTIONS,
|
||||
DEFAULT_LANGUAGE,
|
||||
FILTERED_STATUS,
|
||||
FILTERED,
|
||||
} from './constants';
|
||||
|
||||
/**
|
||||
|
@ -418,3 +420,9 @@ export const createOnBlurHandler = (event, input, normalizeOnBlur) => (
|
|||
normalizeOnBlur
|
||||
? input.onBlur(normalizeOnBlur(event.target.value))
|
||||
: input.onBlur());
|
||||
|
||||
export const checkFiltered = reason => reason.indexOf(FILTERED) === 0;
|
||||
export const checkRewrite = reason => reason === FILTERED_STATUS.REWRITE;
|
||||
export const checkBlackList = reason => reason === FILTERED_STATUS.FILTERED_BLACK_LIST;
|
||||
export const checkWhiteList = reason => reason === FILTERED_STATUS.NOT_FILTERED_WHITE_LIST;
|
||||
export const checkNotFilteredNotFound = reason => reason === FILTERED_STATUS.NOT_FILTERED_NOT_FOUND;
|
||||
|
|
|
@ -79,6 +79,14 @@ const filtering = handleActions(
|
|||
...payload,
|
||||
processingSetConfig: false,
|
||||
}),
|
||||
|
||||
[actions.checkHostRequest]: state => ({ ...state, processingCheck: true }),
|
||||
[actions.checkHostFailure]: state => ({ ...state, processingCheck: false }),
|
||||
[actions.checkHostSuccess]: (state, { payload }) => ({
|
||||
...state,
|
||||
check: payload,
|
||||
processingCheck: false,
|
||||
}),
|
||||
},
|
||||
{
|
||||
isModalOpen: false,
|
||||
|
@ -89,6 +97,7 @@ const filtering = handleActions(
|
|||
processingConfigFilter: false,
|
||||
processingRemoveFilter: false,
|
||||
processingSetConfig: false,
|
||||
processingCheck: false,
|
||||
isFilterAdded: false,
|
||||
filters: [],
|
||||
userRules: '',
|
||||
|
@ -96,6 +105,7 @@ const filtering = handleActions(
|
|||
enabled: true,
|
||||
modalType: '',
|
||||
modalFilterUrl: '',
|
||||
check: {},
|
||||
},
|
||||
);
|
||||
|
||||
|
|
Loading…
Reference in New Issue