mirror of
https://github.com/AdguardTeam/AdGuardHome.git
synced 2024-11-16 10:28:29 -07:00
Merge: + DNS: Ability to check from UI if a host name is filtered
Close #856 * commit '8ec7c37715e410c5564c512162be03383b577e39': + client: handle check host + GET /filtering/check_host: Check if host name is filtered
This commit is contained in:
commit
e27cbdf81b
@ -56,6 +56,7 @@ Contents:
|
|||||||
* API: Get filtering parameters
|
* API: Get filtering parameters
|
||||||
* API: Set filtering parameters
|
* API: Set filtering parameters
|
||||||
* API: Set URL parameters
|
* API: Set URL parameters
|
||||||
|
* API: Domain Check
|
||||||
* Log-in page
|
* Log-in page
|
||||||
* API: Log in
|
* API: Log in
|
||||||
* API: Log out
|
* API: Log out
|
||||||
@ -1355,6 +1356,30 @@ Response:
|
|||||||
200 OK
|
200 OK
|
||||||
|
|
||||||
|
|
||||||
|
### API: Domain Check
|
||||||
|
|
||||||
|
Check if host name is filtered.
|
||||||
|
|
||||||
|
Request:
|
||||||
|
|
||||||
|
GET /control/filtering/check_host?name=hostname
|
||||||
|
|
||||||
|
Response:
|
||||||
|
|
||||||
|
200 OK
|
||||||
|
|
||||||
|
{
|
||||||
|
"reason":"FilteredBlackList",
|
||||||
|
"filter_id":1,
|
||||||
|
"rule":"||doubleclick.net^",
|
||||||
|
"service_name": "...", // set if reason=FilteredBlockedService
|
||||||
|
|
||||||
|
// if reason=ReasonRewrite:
|
||||||
|
"cname": "...",
|
||||||
|
"ip_addrs": ["1.2.3.4", ...],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
## Log-in page
|
## Log-in page
|
||||||
|
|
||||||
After user completes the steps of installation wizard, he must log in into dashboard using his name and password. After user successfully logs in, he gets the Cookie which allows the server to authenticate him next time without password. After the Cookie is expired, user needs to perform log-in operation again.
|
After user completes the steps of installation wizard, he must log in into dashboard using his name and password. After user successfully logs in, he gets the Cookie which allows the server to authenticate him next time without password. After the Cookie is expired, user needs to perform log-in operation again.
|
||||||
|
@ -446,5 +446,17 @@
|
|||||||
"autofix_warning_result": "As a result all DNS requests from your system will be processed by AdGuardHome by default.",
|
"autofix_warning_result": "As a result all DNS requests from your system will be processed by AdGuardHome by default.",
|
||||||
"tags_title": "Tags",
|
"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>",
|
"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());
|
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_REFRESH = { path: 'filtering/refresh', method: 'POST' };
|
||||||
FILTERING_SET_URL = { path: 'filtering/set_url', method: 'POST' };
|
FILTERING_SET_URL = { path: 'filtering/set_url', method: 'POST' };
|
||||||
FILTERING_CONFIG = { path: 'filtering/config', method: 'POST' };
|
FILTERING_CONFIG = { path: 'filtering/config', method: 'POST' };
|
||||||
|
FILTERING_CHECK_HOST = { path: 'filtering/check_host', method: 'GET' };
|
||||||
|
|
||||||
getFilteringStatus() {
|
getFilteringStatus() {
|
||||||
const { path, method } = this.FILTERING_STATUS;
|
const { path, method } = this.FILTERING_STATUS;
|
||||||
@ -141,6 +142,12 @@ class Api {
|
|||||||
return this.makeRequest(path, method, parameters);
|
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
|
||||||
PARENTAL_STATUS = { path: 'parental/status', method: 'GET' };
|
PARENTAL_STATUS = { path: 'parental/status', method: 'GET' };
|
||||||
PARENTAL_ENABLE = { path: 'parental/enable', method: 'POST' };
|
PARENTAL_ENABLE = { path: 'parental/enable', method: 'POST' };
|
||||||
|
127
client/src/components/Filters/Check/Info.js
Normal file
127
client/src/components/Filters/Check/Info.js
Normal file
@ -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);
|
95
client/src/components/Filters/Check/index.js
Normal file
95
client/src/components/Filters/Check/index.js
Normal file
@ -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">
|
<div className="card-actions">
|
||||||
<button
|
<button
|
||||||
className="btn btn-success btn-standard"
|
className="btn btn-success btn-standard btn-large"
|
||||||
type="submit"
|
type="submit"
|
||||||
onClick={this.handleSubmit}
|
onClick={this.handleSubmit}
|
||||||
>
|
>
|
||||||
|
@ -8,8 +8,9 @@ import Card from '../ui/Card';
|
|||||||
import CellWrap from '../ui/CellWrap';
|
import CellWrap from '../ui/CellWrap';
|
||||||
import UserRules from './UserRules';
|
import UserRules from './UserRules';
|
||||||
import Modal from './Modal';
|
import Modal from './Modal';
|
||||||
import { formatDetailedDateTime } from '../../helpers/helpers';
|
import Check from './Check';
|
||||||
|
|
||||||
|
import { formatDetailedDateTime } from '../../helpers/helpers';
|
||||||
import { MODAL_TYPE } from '../../helpers/constants';
|
import { MODAL_TYPE } from '../../helpers/constants';
|
||||||
|
|
||||||
class Filters extends Component {
|
class Filters extends Component {
|
||||||
@ -76,6 +77,10 @@ class Filters extends Component {
|
|||||||
return { name: '', url: '' };
|
return { name: '', url: '' };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
handleCheck = (values) => {
|
||||||
|
this.props.checkHost(values);
|
||||||
|
}
|
||||||
|
|
||||||
columns = [
|
columns = [
|
||||||
{
|
{
|
||||||
Header: <Trans>enabled_table_header</Trans>,
|
Header: <Trans>enabled_table_header</Trans>,
|
||||||
@ -180,6 +185,8 @@ class Filters extends Component {
|
|||||||
processingFilters,
|
processingFilters,
|
||||||
modalType,
|
modalType,
|
||||||
modalFilterUrl,
|
modalFilterUrl,
|
||||||
|
processingCheck,
|
||||||
|
check,
|
||||||
} = filtering;
|
} = filtering;
|
||||||
|
|
||||||
const currentFilterData = this.getFilter(modalFilterUrl, filters);
|
const currentFilterData = this.getFilter(modalFilterUrl, filters);
|
||||||
@ -216,7 +223,7 @@ class Filters extends Component {
|
|||||||
/>
|
/>
|
||||||
<div className="card-actions">
|
<div className="card-actions">
|
||||||
<button
|
<button
|
||||||
className="btn btn-success btn-standard mr-2"
|
className="btn btn-success btn-standard mr-2 btn-large"
|
||||||
type="submit"
|
type="submit"
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
toggleFilteringModal({ type: MODAL_TYPE.ADD })
|
toggleFilteringModal({ type: MODAL_TYPE.ADD })
|
||||||
@ -242,6 +249,14 @@ class Filters extends Component {
|
|||||||
handleRulesSubmit={this.handleRulesSubmit}
|
handleRulesSubmit={this.handleRulesSubmit}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="col-md-12">
|
||||||
|
<Check
|
||||||
|
filters={filters}
|
||||||
|
check={check}
|
||||||
|
onSubmit={this.handleCheck}
|
||||||
|
processing={processingCheck}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Modal
|
<Modal
|
||||||
@ -274,6 +289,7 @@ Filters.propTypes = {
|
|||||||
processingConfigFilter: PropTypes.bool.isRequired,
|
processingConfigFilter: PropTypes.bool.isRequired,
|
||||||
processingRemoveFilter: PropTypes.bool.isRequired,
|
processingRemoveFilter: PropTypes.bool.isRequired,
|
||||||
modalType: PropTypes.string.isRequired,
|
modalType: PropTypes.string.isRequired,
|
||||||
|
processingCheck: PropTypes.bool.isRequired,
|
||||||
}),
|
}),
|
||||||
removeFilter: PropTypes.func.isRequired,
|
removeFilter: PropTypes.func.isRequired,
|
||||||
toggleFilterStatus: PropTypes.func.isRequired,
|
toggleFilterStatus: PropTypes.func.isRequired,
|
||||||
@ -282,6 +298,7 @@ Filters.propTypes = {
|
|||||||
handleRulesChange: PropTypes.func.isRequired,
|
handleRulesChange: PropTypes.func.isRequired,
|
||||||
refreshFilters: PropTypes.func.isRequired,
|
refreshFilters: PropTypes.func.isRequired,
|
||||||
editFilter: PropTypes.func.isRequired,
|
editFilter: PropTypes.func.isRequired,
|
||||||
|
checkHost: PropTypes.func.isRequired,
|
||||||
t: PropTypes.func.isRequired,
|
t: PropTypes.func.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -112,3 +112,15 @@
|
|||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.card .red {
|
||||||
|
background-color: #fff4f2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card .green {
|
||||||
|
background-color: #f1faf3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card .blue {
|
||||||
|
background-color: #ecf7ff;
|
||||||
|
}
|
||||||
|
@ -9,6 +9,7 @@ import {
|
|||||||
refreshFilters,
|
refreshFilters,
|
||||||
handleRulesChange,
|
handleRulesChange,
|
||||||
editFilter,
|
editFilter,
|
||||||
|
checkHost,
|
||||||
} from '../actions/filtering';
|
} from '../actions/filtering';
|
||||||
import Filters from '../components/Filters';
|
import Filters from '../components/Filters';
|
||||||
|
|
||||||
@ -28,6 +29,7 @@ const mapDispatchToProps = {
|
|||||||
refreshFilters,
|
refreshFilters,
|
||||||
handleRulesChange,
|
handleRulesChange,
|
||||||
editFilter,
|
editFilter,
|
||||||
|
checkHost,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default connect(
|
export default connect(
|
||||||
|
@ -349,10 +349,14 @@ export const ENCRYPTION_SOURCE = {
|
|||||||
export const FILTERED_STATUS = {
|
export const FILTERED_STATUS = {
|
||||||
FILTERED_BLACK_LIST: 'FilteredBlackList',
|
FILTERED_BLACK_LIST: 'FilteredBlackList',
|
||||||
NOT_FILTERED_WHITE_LIST: 'NotFilteredWhiteList',
|
NOT_FILTERED_WHITE_LIST: 'NotFilteredWhiteList',
|
||||||
|
NOT_FILTERED_NOT_FOUND: 'NotFilteredNotFound',
|
||||||
FILTERED_BLOCKED_SERVICE: 'FilteredBlockedService',
|
FILTERED_BLOCKED_SERVICE: 'FilteredBlockedService',
|
||||||
REWRITE: 'Rewrite',
|
REWRITE: 'Rewrite',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const FILTERED = 'Filtered';
|
||||||
|
export const NOT_FILTERED = 'NotFiltered';
|
||||||
|
|
||||||
export const STATS_INTERVALS_DAYS = [1, 7, 30, 90];
|
export const STATS_INTERVALS_DAYS = [1, 7, 30, 90];
|
||||||
|
|
||||||
export const QUERY_LOG_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,
|
DEFAULT_DATE_FORMAT_OPTIONS,
|
||||||
DETAILED_DATE_FORMAT_OPTIONS,
|
DETAILED_DATE_FORMAT_OPTIONS,
|
||||||
DEFAULT_LANGUAGE,
|
DEFAULT_LANGUAGE,
|
||||||
|
FILTERED_STATUS,
|
||||||
|
FILTERED,
|
||||||
} from './constants';
|
} from './constants';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -418,3 +420,9 @@ export const createOnBlurHandler = (event, input, normalizeOnBlur) => (
|
|||||||
normalizeOnBlur
|
normalizeOnBlur
|
||||||
? input.onBlur(normalizeOnBlur(event.target.value))
|
? input.onBlur(normalizeOnBlur(event.target.value))
|
||||||
: input.onBlur());
|
: 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,
|
...payload,
|
||||||
processingSetConfig: false,
|
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,
|
isModalOpen: false,
|
||||||
@ -89,6 +97,7 @@ const filtering = handleActions(
|
|||||||
processingConfigFilter: false,
|
processingConfigFilter: false,
|
||||||
processingRemoveFilter: false,
|
processingRemoveFilter: false,
|
||||||
processingSetConfig: false,
|
processingSetConfig: false,
|
||||||
|
processingCheck: false,
|
||||||
isFilterAdded: false,
|
isFilterAdded: false,
|
||||||
filters: [],
|
filters: [],
|
||||||
userRules: '',
|
userRules: '',
|
||||||
@ -96,6 +105,7 @@ const filtering = handleActions(
|
|||||||
enabled: true,
|
enabled: true,
|
||||||
modalType: '',
|
modalType: '',
|
||||||
modalFilterUrl: '',
|
modalFilterUrl: '',
|
||||||
|
check: {},
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
@ -11,6 +12,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/AdguardTeam/golibs/log"
|
"github.com/AdguardTeam/golibs/log"
|
||||||
|
"github.com/miekg/dns"
|
||||||
)
|
)
|
||||||
|
|
||||||
// IsValidURL - return TRUE if URL is valid
|
// IsValidURL - return TRUE if URL is valid
|
||||||
@ -290,15 +292,58 @@ func handleFilteringConfig(w http.ResponseWriter, r *http.Request) {
|
|||||||
enableFilters(true)
|
enableFilters(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type checkHostResp struct {
|
||||||
|
Reason string `json:"reason"`
|
||||||
|
FilterID int64 `json:"filter_id"`
|
||||||
|
Rule string `json:"rule"`
|
||||||
|
|
||||||
|
// for FilteredBlockedService:
|
||||||
|
SvcName string `json:"service_name"`
|
||||||
|
|
||||||
|
// for ReasonRewrite:
|
||||||
|
CanonName string `json:"cname"` // CNAME value
|
||||||
|
IPList []net.IP `json:"ip_addrs"` // list of IP addresses
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleCheckHost(w http.ResponseWriter, r *http.Request) {
|
||||||
|
q := r.URL.Query()
|
||||||
|
host := q.Get("name")
|
||||||
|
|
||||||
|
setts := Context.dnsFilter.GetConfig()
|
||||||
|
setts.FilteringEnabled = true
|
||||||
|
ApplyBlockedServices(&setts, config.DNS.BlockedServices)
|
||||||
|
result, err := Context.dnsFilter.CheckHost(host, dns.TypeA, &setts)
|
||||||
|
if err != nil {
|
||||||
|
httpError(w, http.StatusInternalServerError, "couldn't apply filtering: %s: %s", host, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resp := checkHostResp{}
|
||||||
|
resp.Reason = result.Reason.String()
|
||||||
|
resp.FilterID = result.FilterID
|
||||||
|
resp.Rule = result.Rule
|
||||||
|
resp.SvcName = result.ServiceName
|
||||||
|
resp.CanonName = result.CanonName
|
||||||
|
resp.IPList = result.IPList
|
||||||
|
js, err := json.Marshal(resp)
|
||||||
|
if err != nil {
|
||||||
|
httpError(w, http.StatusInternalServerError, "json encode: %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
_, _ = w.Write(js)
|
||||||
|
}
|
||||||
|
|
||||||
// RegisterFilteringHandlers - register handlers
|
// RegisterFilteringHandlers - register handlers
|
||||||
func RegisterFilteringHandlers() {
|
func RegisterFilteringHandlers() {
|
||||||
httpRegister(http.MethodGet, "/control/filtering/status", handleFilteringStatus)
|
httpRegister("GET", "/control/filtering/status", handleFilteringStatus)
|
||||||
httpRegister(http.MethodPost, "/control/filtering/config", handleFilteringConfig)
|
httpRegister("POST", "/control/filtering/config", handleFilteringConfig)
|
||||||
httpRegister(http.MethodPost, "/control/filtering/add_url", handleFilteringAddURL)
|
httpRegister("POST", "/control/filtering/add_url", handleFilteringAddURL)
|
||||||
httpRegister(http.MethodPost, "/control/filtering/remove_url", handleFilteringRemoveURL)
|
httpRegister("POST", "/control/filtering/remove_url", handleFilteringRemoveURL)
|
||||||
httpRegister(http.MethodPost, "/control/filtering/set_url", handleFilteringSetURL)
|
httpRegister("POST", "/control/filtering/set_url", handleFilteringSetURL)
|
||||||
httpRegister(http.MethodPost, "/control/filtering/refresh", handleFilteringRefresh)
|
httpRegister("POST", "/control/filtering/refresh", handleFilteringRefresh)
|
||||||
httpRegister(http.MethodPost, "/control/filtering/set_rules", handleFilteringSetRules)
|
httpRegister("POST", "/control/filtering/set_rules", handleFilteringSetRules)
|
||||||
|
httpRegister("GET", "/control/filtering/check_host", handleCheckHost)
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkFiltersUpdateIntervalHours(i uint32) bool {
|
func checkFiltersUpdateIntervalHours(i uint32) bool {
|
||||||
|
@ -2,7 +2,7 @@ swagger: '2.0'
|
|||||||
info:
|
info:
|
||||||
title: 'AdGuard Home'
|
title: 'AdGuard Home'
|
||||||
description: 'AdGuard Home REST API. Admin web interface is built on top of this REST API.'
|
description: 'AdGuard Home REST API. Admin web interface is built on top of this REST API.'
|
||||||
version: '0.99.3'
|
version: '0.101'
|
||||||
schemes:
|
schemes:
|
||||||
- http
|
- http
|
||||||
basePath: /control
|
basePath: /control
|
||||||
@ -594,6 +594,22 @@ paths:
|
|||||||
200:
|
200:
|
||||||
description: OK
|
description: OK
|
||||||
|
|
||||||
|
/filtering/check_host:
|
||||||
|
get:
|
||||||
|
tags:
|
||||||
|
- filtering
|
||||||
|
operationId: filteringCheckHost
|
||||||
|
summary: 'Check if host name is filtered'
|
||||||
|
parameters:
|
||||||
|
- name: name
|
||||||
|
in: query
|
||||||
|
type: string
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
description: OK
|
||||||
|
schema:
|
||||||
|
$ref: "#/definitions/FilterCheckHostResponse"
|
||||||
|
|
||||||
# --------------------------------------------------
|
# --------------------------------------------------
|
||||||
# Safebrowsing methods
|
# Safebrowsing methods
|
||||||
# --------------------------------------------------
|
# --------------------------------------------------
|
||||||
@ -1178,6 +1194,42 @@ definitions:
|
|||||||
enabled:
|
enabled:
|
||||||
type: "boolean"
|
type: "boolean"
|
||||||
|
|
||||||
|
FilterCheckHostResponse:
|
||||||
|
type: "object"
|
||||||
|
description: "Check Host Result"
|
||||||
|
properties:
|
||||||
|
reason:
|
||||||
|
type: "string"
|
||||||
|
description: "DNS filter status"
|
||||||
|
enum:
|
||||||
|
- "NotFilteredNotFound"
|
||||||
|
- "NotFilteredWhiteList"
|
||||||
|
- "NotFilteredError"
|
||||||
|
- "FilteredBlackList"
|
||||||
|
- "FilteredSafeBrowsing"
|
||||||
|
- "FilteredParental"
|
||||||
|
- "FilteredInvalid"
|
||||||
|
- "FilteredSafeSearch"
|
||||||
|
- "FilteredBlockedService"
|
||||||
|
- "ReasonRewrite"
|
||||||
|
filter_id:
|
||||||
|
type: "integer"
|
||||||
|
rule:
|
||||||
|
type: "string"
|
||||||
|
example: "||example.org^"
|
||||||
|
description: "Filtering rule applied to the request (if any)"
|
||||||
|
service_name:
|
||||||
|
type: "string"
|
||||||
|
description: "Set if reason=FilteredBlockedService"
|
||||||
|
cname:
|
||||||
|
type: "string"
|
||||||
|
description: "Set if reason=ReasonRewrite"
|
||||||
|
ip_addrs:
|
||||||
|
type: "array"
|
||||||
|
items:
|
||||||
|
type: "string"
|
||||||
|
description: "Set if reason=ReasonRewrite"
|
||||||
|
|
||||||
GetVersionRequest:
|
GetVersionRequest:
|
||||||
type: "object"
|
type: "object"
|
||||||
description: "/version.json request data"
|
description: "/version.json request data"
|
||||||
@ -1471,6 +1523,7 @@ definitions:
|
|||||||
- "FilteredInvalid"
|
- "FilteredInvalid"
|
||||||
- "FilteredSafeSearch"
|
- "FilteredSafeSearch"
|
||||||
- "FilteredBlockedService"
|
- "FilteredBlockedService"
|
||||||
|
- "ReasonRewrite"
|
||||||
service_name:
|
service_name:
|
||||||
type: "string"
|
type: "string"
|
||||||
description: "Set if reason=FilteredBlockedService"
|
description: "Set if reason=FilteredBlockedService"
|
||||||
|
Loading…
Reference in New Issue
Block a user