Merge branch 'master' into 1587-cache-settings
This commit is contained in:
commit
7dd3d944e8
2
client/babel.config.js
vendored
2
client/babel.config.js
vendored
@ -9,6 +9,8 @@ module.exports = (api) => {
|
|||||||
'@babel/plugin-proposal-class-properties',
|
'@babel/plugin-proposal-class-properties',
|
||||||
'@babel/plugin-transform-runtime',
|
'@babel/plugin-transform-runtime',
|
||||||
'@babel/plugin-proposal-object-rest-spread',
|
'@babel/plugin-proposal-object-rest-spread',
|
||||||
|
'@babel/plugin-proposal-nullish-coalescing-operator',
|
||||||
|
'@babel/plugin-proposal-optional-chaining',
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
32
client/package-lock.json
generated
vendored
32
client/package-lock.json
generated
vendored
@ -472,13 +472,21 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@babel/plugin-proposal-nullish-coalescing-operator": {
|
"@babel/plugin-proposal-nullish-coalescing-operator": {
|
||||||
"version": "7.8.3",
|
"version": "7.10.4",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.8.3.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.10.4.tgz",
|
||||||
"integrity": "sha512-TS9MlfzXpXKt6YYomudb/KU7nQI6/xnapG6in1uZxoxDghuSMZsPb6D2fyUwNYSAp4l1iR7QtFOjkqcRYcUsfw==",
|
"integrity": "sha512-wq5n1M3ZUlHl9sqT2ok1T2/MTt6AXE0e1Lz4WzWBr95LsAZ5qDXe4KnFuauYyEyLiohvXFMdbsOTMyLZs91Zlw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@babel/helper-plugin-utils": "^7.8.3",
|
"@babel/helper-plugin-utils": "^7.10.4",
|
||||||
"@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0"
|
"@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/helper-plugin-utils": {
|
||||||
|
"version": "7.10.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz",
|
||||||
|
"integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@babel/plugin-proposal-numeric-separator": {
|
"@babel/plugin-proposal-numeric-separator": {
|
||||||
@ -513,13 +521,21 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@babel/plugin-proposal-optional-chaining": {
|
"@babel/plugin-proposal-optional-chaining": {
|
||||||
"version": "7.9.0",
|
"version": "7.10.4",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.9.0.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.10.4.tgz",
|
||||||
"integrity": "sha512-NDn5tu3tcv4W30jNhmc2hyD5c56G6cXx4TesJubhxrJeCvuuMpttxr0OnNCqbZGhFjLrg+NIhxxC+BK5F6yS3w==",
|
"integrity": "sha512-ZIhQIEeavTgouyMSdZRap4VPPHqJJ3NEs2cuHs5p0erH+iz6khB0qfgU8g7UuJkG88+fBMy23ZiU+nuHvekJeQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@babel/helper-plugin-utils": "^7.8.3",
|
"@babel/helper-plugin-utils": "^7.10.4",
|
||||||
"@babel/plugin-syntax-optional-chaining": "^7.8.0"
|
"@babel/plugin-syntax-optional-chaining": "^7.8.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/helper-plugin-utils": {
|
||||||
|
"version": "7.10.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz",
|
||||||
|
"integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@babel/plugin-proposal-unicode-property-regex": {
|
"@babel/plugin-proposal-unicode-property-regex": {
|
||||||
|
2
client/package.json
vendored
2
client/package.json
vendored
@ -44,7 +44,9 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.9.6",
|
"@babel/core": "^7.9.6",
|
||||||
"@babel/plugin-proposal-class-properties": "^7.8.3",
|
"@babel/plugin-proposal-class-properties": "^7.8.3",
|
||||||
|
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.10.4",
|
||||||
"@babel/plugin-proposal-object-rest-spread": "^7.9.6",
|
"@babel/plugin-proposal-object-rest-spread": "^7.9.6",
|
||||||
|
"@babel/plugin-proposal-optional-chaining": "^7.10.4",
|
||||||
"@babel/plugin-transform-runtime": "^7.9.6",
|
"@babel/plugin-transform-runtime": "^7.9.6",
|
||||||
"@babel/preset-env": "^7.9.6",
|
"@babel/preset-env": "^7.9.6",
|
||||||
"@babel/preset-react": "^7.9.4",
|
"@babel/preset-react": "^7.9.4",
|
||||||
|
@ -149,7 +149,7 @@ const checkStatus = async (handleRequestSuccess, handleRequestError, attempts =
|
|||||||
try {
|
try {
|
||||||
const response = await axios.get('control/status');
|
const response = await axios.get('control/status');
|
||||||
rmTimeout(timeout);
|
rmTimeout(timeout);
|
||||||
if (response && response.status === 200) {
|
if (response?.status === 200) {
|
||||||
handleRequestSuccess(response);
|
handleRequestSuccess(response);
|
||||||
if (response.data.running === false) {
|
if (response.data.running === false) {
|
||||||
timeout = setTimeout(
|
timeout = setTimeout(
|
||||||
@ -183,7 +183,7 @@ export const getUpdate = () => async (dispatch, getState) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleRequestSuccess = (response) => {
|
const handleRequestSuccess = (response) => {
|
||||||
const responseVersion = response.data && response.data.version;
|
const responseVersion = response.data?.version;
|
||||||
|
|
||||||
if (dnsVersion !== responseVersion) {
|
if (dnsVersion !== responseVersion) {
|
||||||
dispatch(getUpdateSuccess());
|
dispatch(getUpdateSuccess());
|
||||||
|
@ -17,7 +17,7 @@ const getInitialDataForServices = (initial) => (initial ? initial.reduce(
|
|||||||
const Services = () => {
|
const Services = () => {
|
||||||
const [t] = useTranslation();
|
const [t] = useTranslation();
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const services = useSelector((store) => store && store.services);
|
const services = useSelector((store) => store?.services);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
dispatch(getBlockedServices());
|
dispatch(getBlockedServices());
|
||||||
|
@ -11,23 +11,20 @@ const getClientCell = ({
|
|||||||
row, t, isDetailed, toggleBlocking, autoClients, processingRules,
|
row, t, isDetailed, toggleBlocking, autoClients, processingRules,
|
||||||
}) => {
|
}) => {
|
||||||
const {
|
const {
|
||||||
reason, client, domain, info: { name },
|
reason, client, domain, info: { name, whois_info },
|
||||||
} = row.original;
|
} = row.original;
|
||||||
|
|
||||||
const autoClient = autoClients.find((autoClient) => autoClient.name === client);
|
const autoClient = autoClients.find((autoClient) => autoClient.name === client);
|
||||||
const country = autoClient && autoClient.whois_info && autoClient.whois_info.country;
|
const source = autoClient?.source;
|
||||||
const city = autoClient && autoClient.whois_info && autoClient.whois_info.city;
|
|
||||||
const network = autoClient && autoClient.whois_info && autoClient.whois_info.orgname;
|
|
||||||
const source = autoClient && autoClient.source;
|
|
||||||
|
|
||||||
const id = nanoid();
|
const id = nanoid();
|
||||||
|
|
||||||
const data = {
|
const data = {
|
||||||
address: client,
|
address: client,
|
||||||
name,
|
name,
|
||||||
country,
|
country: whois_info?.country,
|
||||||
city,
|
city: whois_info?.city,
|
||||||
network,
|
network: whois_info?.orgname,
|
||||||
source_label: source,
|
source_label: source,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -57,8 +57,8 @@ const getDomainCell = (props) => {
|
|||||||
const sourceData = getSourceData(tracker);
|
const sourceData = getSourceData(tracker);
|
||||||
|
|
||||||
const knownTrackerDataObj = {
|
const knownTrackerDataObj = {
|
||||||
name_table_header: tracker && tracker.name,
|
name_table_header: tracker?.name,
|
||||||
category_label: tracker && captitalizeWords(tracker.category),
|
category_label: hasTracker && captitalizeWords(tracker.category),
|
||||||
source_label: sourceData
|
source_label: sourceData
|
||||||
&& <a href={sourceData.url} target="_blank" rel="noopener noreferrer"
|
&& <a href={sourceData.url} target="_blank" rel="noopener noreferrer"
|
||||||
className="link--green">{sourceData.name}</a>,
|
className="link--green">{sourceData.name}</a>,
|
||||||
|
@ -36,8 +36,7 @@ const getResponseCell = (row, filtering, t, isDetailed) => {
|
|||||||
const { filters, whitelistFilters } = filtering;
|
const { filters, whitelistFilters } = filtering;
|
||||||
const formattedElapsedMs = formatElapsedMs(elapsedMs, t);
|
const formattedElapsedMs = formatElapsedMs(elapsedMs, t);
|
||||||
|
|
||||||
const statusLabel = t((FILTERED_STATUS_TO_META_MAP[reason]
|
const statusLabel = t(FILTERED_STATUS_TO_META_MAP[reason]?.label || reason);
|
||||||
&& FILTERED_STATUS_TO_META_MAP[reason].label) || reason);
|
|
||||||
const boldStatusLabel = <span className="font-weight-bold">{statusLabel}</span>;
|
const boldStatusLabel = <span className="font-weight-bold">{statusLabel}</span>;
|
||||||
const filter = getFilterName(filters, whitelistFilters, filterId, t);
|
const filter = getFilterName(filters, whitelistFilters, filterId, t);
|
||||||
|
|
||||||
|
@ -1,10 +1,18 @@
|
|||||||
import React from 'react';
|
import React, { useEffect } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { Field, reduxForm } from 'redux-form';
|
import { Field, reduxForm } from 'redux-form';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import debounce from 'lodash/debounce';
|
import debounce from 'lodash/debounce';
|
||||||
import { DEBOUNCE_FILTER_TIMEOUT, FORM_NAME, RESPONSE_FILTER } from '../../../helpers/constants';
|
import { useDispatch } from 'react-redux';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
import {
|
||||||
|
DEBOUNCE_FILTER_TIMEOUT,
|
||||||
|
DEFAULT_LOGS_FILTER,
|
||||||
|
FORM_NAME,
|
||||||
|
RESPONSE_FILTER,
|
||||||
|
} from '../../../helpers/constants';
|
||||||
import Tooltip from '../../ui/Tooltip';
|
import Tooltip from '../../ui/Tooltip';
|
||||||
|
import { setLogsFilter } from '../../../actions/queryLogs';
|
||||||
|
|
||||||
const renderFilterField = ({
|
const renderFilterField = ({
|
||||||
input,
|
input,
|
||||||
@ -16,8 +24,9 @@ const renderFilterField = ({
|
|||||||
autoComplete,
|
autoComplete,
|
||||||
tooltip,
|
tooltip,
|
||||||
meta: { touched, error },
|
meta: { touched, error },
|
||||||
|
onClearInputClick,
|
||||||
}) => <>
|
}) => <>
|
||||||
<div className="input-group-search">
|
<div className="input-group-search input-group-search__icon--magnifier">
|
||||||
<svg className="icons icon--small icon--gray">
|
<svg className="icons icon--small icon--gray">
|
||||||
<use xlinkHref="#magnifier" />
|
<use xlinkHref="#magnifier" />
|
||||||
</svg>
|
</svg>
|
||||||
@ -31,9 +40,15 @@ const renderFilterField = ({
|
|||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
autoComplete={autoComplete}
|
autoComplete={autoComplete}
|
||||||
aria-label={placeholder} />
|
aria-label={placeholder} />
|
||||||
<span className="logs__notice">
|
<div
|
||||||
<Tooltip text={tooltip} type='tooltip-custom--logs' />
|
className={classNames('input-group-search input-group-search__icon--cross', { invisible: input.value.length < 1 })}>
|
||||||
</span>
|
<svg className="icons icon--smallest icon--gray" onClick={onClearInputClick}>
|
||||||
|
<use xlinkHref="#cross" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<span className="input-group-search input-group-search__icon--tooltip">
|
||||||
|
<Tooltip text={tooltip} type='tooltip-custom--logs' />
|
||||||
|
</span>
|
||||||
{!disabled
|
{!disabled
|
||||||
&& touched
|
&& touched
|
||||||
&& (error && <span className="form__message form__message--error">{error}</span>)}
|
&& (error && <span className="form__message form__message--error">{error}</span>)}
|
||||||
@ -42,6 +57,7 @@ const renderFilterField = ({
|
|||||||
renderFilterField.propTypes = {
|
renderFilterField.propTypes = {
|
||||||
input: PropTypes.object.isRequired,
|
input: PropTypes.object.isRequired,
|
||||||
id: PropTypes.string.isRequired,
|
id: PropTypes.string.isRequired,
|
||||||
|
onClearInputClick: PropTypes.func.isRequired,
|
||||||
className: PropTypes.string,
|
className: PropTypes.string,
|
||||||
placeholder: PropTypes.string,
|
placeholder: PropTypes.string,
|
||||||
type: PropTypes.string,
|
type: PropTypes.string,
|
||||||
@ -59,13 +75,29 @@ const Form = (props) => {
|
|||||||
className = '',
|
className = '',
|
||||||
responseStatusClass,
|
responseStatusClass,
|
||||||
submit,
|
submit,
|
||||||
|
reset,
|
||||||
|
setIsLoading,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const [t] = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
const debouncedSubmit = debounce(submit, DEBOUNCE_FILTER_TIMEOUT);
|
const debouncedSubmit = debounce(submit, DEBOUNCE_FILTER_TIMEOUT);
|
||||||
const zeroDelaySubmit = () => setTimeout(submit, 0);
|
const zeroDelaySubmit = () => setTimeout(submit, 0);
|
||||||
|
|
||||||
|
const clearInput = async () => {
|
||||||
|
await dispatch(setLogsFilter(DEFAULT_LOGS_FILTER));
|
||||||
|
await reset();
|
||||||
|
};
|
||||||
|
|
||||||
|
const onInputClear = async () => {
|
||||||
|
setIsLoading(true);
|
||||||
|
await clearInput();
|
||||||
|
setIsLoading(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => clearInput, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form className="d-flex flex-wrap form-control--container"
|
<form className="d-flex flex-wrap form-control--container"
|
||||||
onSubmit={(e) => {
|
onSubmit={(e) => {
|
||||||
@ -79,16 +111,17 @@ const Form = (props) => {
|
|||||||
name="search"
|
name="search"
|
||||||
component={renderFilterField}
|
component={renderFilterField}
|
||||||
type="text"
|
type="text"
|
||||||
className={`form-control--search form-control--transparent ${className}`}
|
className={classNames('form-control--search form-control--transparent', className)}
|
||||||
placeholder={t('domain_or_client')}
|
placeholder={t('domain_or_client')}
|
||||||
tooltip={t('query_log_strict_search')}
|
tooltip={t('query_log_strict_search')}
|
||||||
onChange={debouncedSubmit}
|
onChange={debouncedSubmit}
|
||||||
|
onClearInputClick={onInputClear}
|
||||||
/>
|
/>
|
||||||
<div className="field__select">
|
<div className="field__select">
|
||||||
<Field
|
<Field
|
||||||
name="response_status"
|
name="response_status"
|
||||||
component="select"
|
component="select"
|
||||||
className={`form-control custom-select custom-select--logs custom-select__arrow--left ml-small form-control--transparent ${responseStatusClass}`}
|
className={classNames('form-control custom-select custom-select--logs custom-select__arrow--left ml-small form-control--transparent', responseStatusClass)}
|
||||||
onChange={zeroDelaySubmit}
|
onChange={zeroDelaySubmit}
|
||||||
>
|
>
|
||||||
{Object.values(RESPONSE_FILTER)
|
{Object.values(RESPONSE_FILTER)
|
||||||
@ -107,6 +140,8 @@ Form.propTypes = {
|
|||||||
className: PropTypes.string,
|
className: PropTypes.string,
|
||||||
responseStatusClass: PropTypes.string,
|
responseStatusClass: PropTypes.string,
|
||||||
submit: PropTypes.func.isRequired,
|
submit: PropTypes.func.isRequired,
|
||||||
|
reset: PropTypes.func.isRequired,
|
||||||
|
setIsLoading: PropTypes.func.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default reduxForm({
|
export default reduxForm({
|
||||||
|
@ -33,7 +33,8 @@ const Filters = ({ filter, refreshLogs, setIsLoading }) => {
|
|||||||
responseStatusClass="d-sm-block"
|
responseStatusClass="d-sm-block"
|
||||||
initialValues={filter}
|
initialValues={filter}
|
||||||
onSubmit={onSubmit}
|
onSubmit={onSubmit}
|
||||||
/>
|
setIsLoading={setIsLoading}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -199,17 +199,6 @@
|
|||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.logs__notice {
|
|
||||||
position: relative;
|
|
||||||
z-index: 1;
|
|
||||||
top: 0.5rem;
|
|
||||||
right: 2rem;
|
|
||||||
margin-top: 0.1875rem;
|
|
||||||
font-size: 0.75rem;
|
|
||||||
text-align: left;
|
|
||||||
color: var(--gray-a5);
|
|
||||||
}
|
|
||||||
|
|
||||||
.logs__whois {
|
.logs__whois {
|
||||||
display: inline;
|
display: inline;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
@ -485,10 +474,22 @@
|
|||||||
.input-group-search {
|
.input-group-search {
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
position: relative;
|
position: relative;
|
||||||
left: 2rem;
|
|
||||||
top: 0.4rem;
|
|
||||||
width: 1.5rem;
|
width: 1.5rem;
|
||||||
height: 1.5rem;
|
height: 1.5rem;
|
||||||
|
top: 0.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-group-search__icon--magnifier {
|
||||||
|
left: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-group-search__icon--cross {
|
||||||
|
left: -4.5rem;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-group-search__icon--tooltip {
|
||||||
|
left: -4rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-control--container {
|
.form-control--container {
|
||||||
|
@ -180,6 +180,7 @@ const Table = (props) => {
|
|||||||
minWidth: 123,
|
minWidth: 123,
|
||||||
maxHeight: 60,
|
maxHeight: 60,
|
||||||
headerClassName: 'logs__text',
|
headerClassName: 'logs__text',
|
||||||
|
className: 'pb-0',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -279,20 +280,15 @@ const Table = (props) => {
|
|||||||
|
|
||||||
const hasTracker = !!tracker;
|
const hasTracker = !!tracker;
|
||||||
|
|
||||||
const autoClient = autoClients.find(
|
const autoClient = autoClients
|
||||||
(autoClient) => autoClient.name === client,
|
.find((autoClient) => autoClient.name === client);
|
||||||
);
|
|
||||||
|
|
||||||
const country = autoClient && autoClient.whois_info
|
const { whois_info } = info;
|
||||||
&& autoClient.whois_info.country;
|
const country = whois_info?.country;
|
||||||
|
const city = whois_info?.city;
|
||||||
|
const network = whois_info?.orgname;
|
||||||
|
|
||||||
const network = autoClient && autoClient.whois_info
|
const source = autoClient?.source;
|
||||||
&& autoClient.whois_info.orgname;
|
|
||||||
|
|
||||||
const city = autoClient && autoClient.whois_info
|
|
||||||
&& autoClient.whois_info.city;
|
|
||||||
|
|
||||||
const source = autoClient && autoClient.source;
|
|
||||||
|
|
||||||
const formattedElapsedMs = formatElapsedMs(elapsedMs, t);
|
const formattedElapsedMs = formatElapsedMs(elapsedMs, t);
|
||||||
const isFiltered = checkFiltered(reason);
|
const isFiltered = checkFiltered(reason);
|
||||||
@ -302,8 +298,7 @@ const Table = (props) => {
|
|||||||
toggleBlocking(buttonType, domain);
|
toggleBlocking(buttonType, domain);
|
||||||
};
|
};
|
||||||
|
|
||||||
const status = t((FILTERED_STATUS_TO_META_MAP[reason]
|
const status = t(FILTERED_STATUS_TO_META_MAP[reason]?.label || reason);
|
||||||
&& FILTERED_STATUS_TO_META_MAP[reason].label) || reason);
|
|
||||||
const statusBlocked = <div className="bg--danger">{status}</div>;
|
const statusBlocked = <div className="bg--danger">{status}</div>;
|
||||||
|
|
||||||
const protocol = t(SCHEME_TO_PROTOCOL_MAP[client_proto]) || '';
|
const protocol = t(SCHEME_TO_PROTOCOL_MAP[client_proto]) || '';
|
||||||
@ -318,7 +313,7 @@ const Table = (props) => {
|
|||||||
type_table_header: type,
|
type_table_header: type,
|
||||||
protocol,
|
protocol,
|
||||||
known_tracker: hasTracker && 'title',
|
known_tracker: hasTracker && 'title',
|
||||||
table_name: hasTracker && tracker.name,
|
table_name: tracker?.name,
|
||||||
category_label: hasTracker && captitalizeWords(tracker.category),
|
category_label: hasTracker && captitalizeWords(tracker.category),
|
||||||
tracker_source: hasTracker && sourceData
|
tracker_source: hasTracker && sourceData
|
||||||
&& <a href={sourceData.url} target="_blank" rel="noopener noreferrer"
|
&& <a href={sourceData.url} target="_blank" rel="noopener noreferrer"
|
||||||
@ -326,17 +321,17 @@ const Table = (props) => {
|
|||||||
response_details: 'title',
|
response_details: 'title',
|
||||||
install_settings_dns: upstream,
|
install_settings_dns: upstream,
|
||||||
elapsed: formattedElapsedMs,
|
elapsed: formattedElapsedMs,
|
||||||
response_table_header: response && response.join('\n'),
|
response_table_header: response?.join('\n'),
|
||||||
client_details: 'title',
|
client_details: 'title',
|
||||||
ip_address: client,
|
ip_address: client,
|
||||||
name: info && info.name,
|
name: info?.name,
|
||||||
country,
|
country,
|
||||||
city,
|
city,
|
||||||
network,
|
network,
|
||||||
source_label: source,
|
source_label: source,
|
||||||
validated_with_dnssec: dnssec_enabled ? Boolean(answer_dnssec) : false,
|
validated_with_dnssec: dnssec_enabled ? Boolean(answer_dnssec) : false,
|
||||||
[buttonType]: <div onClick={onToggleBlock}
|
[buttonType]: <div onClick={onToggleBlock}
|
||||||
className="title--border bg--danger">{t(buttonType)}</div>,
|
className="title--border bg--danger text-center">{t(buttonType)}</div>,
|
||||||
};
|
};
|
||||||
|
|
||||||
const detailedDataBlocked = {
|
const detailedDataBlocked = {
|
||||||
@ -347,7 +342,7 @@ const Table = (props) => {
|
|||||||
type_table_header: type,
|
type_table_header: type,
|
||||||
protocol,
|
protocol,
|
||||||
known_tracker: 'title',
|
known_tracker: 'title',
|
||||||
table_name: hasTracker && tracker.name,
|
table_name: tracker?.name,
|
||||||
category_label: hasTracker && captitalizeWords(tracker.category),
|
category_label: hasTracker && captitalizeWords(tracker.category),
|
||||||
source_label: hasTracker && sourceData
|
source_label: hasTracker && sourceData
|
||||||
&& <a href={sourceData.url} target="_blank" rel="noopener noreferrer"
|
&& <a href={sourceData.url} target="_blank" rel="noopener noreferrer"
|
||||||
@ -355,9 +350,9 @@ const Table = (props) => {
|
|||||||
response_details: 'title',
|
response_details: 'title',
|
||||||
install_settings_dns: upstream,
|
install_settings_dns: upstream,
|
||||||
elapsed: formattedElapsedMs,
|
elapsed: formattedElapsedMs,
|
||||||
response_table_header: response && response.join('\n'),
|
response_table_header: response?.join('\n'),
|
||||||
[buttonType]: <div onClick={onToggleBlock}
|
[buttonType]: <div onClick={onToggleBlock}
|
||||||
className="title--border">{t(buttonType)}</div>,
|
className="title--border text-center">{t(buttonType)}</div>,
|
||||||
};
|
};
|
||||||
|
|
||||||
const detailedDataCurrent = isFiltered ? detailedDataBlocked : detailedData;
|
const detailedDataCurrent = isFiltered ? detailedDataBlocked : detailedData;
|
||||||
|
@ -12,12 +12,12 @@ import Loading from '../ui/Loading';
|
|||||||
import Filters from './Filters';
|
import Filters from './Filters';
|
||||||
import Table from './Table';
|
import Table from './Table';
|
||||||
import Disabled from './Disabled';
|
import Disabled from './Disabled';
|
||||||
import './Logs.css';
|
|
||||||
import { getFilteringStatus } from '../../actions/filtering';
|
import { getFilteringStatus } from '../../actions/filtering';
|
||||||
import { getClients } from '../../actions';
|
import { getClients } from '../../actions';
|
||||||
import { getDnsConfig } from '../../actions/dnsConfig';
|
import { getDnsConfig } from '../../actions/dnsConfig';
|
||||||
import { getLogsConfig } from '../../actions/queryLogs';
|
import { getLogsConfig } from '../../actions/queryLogs';
|
||||||
import { addSuccessToast } from '../../actions/toasts';
|
import { addSuccessToast } from '../../actions/toasts';
|
||||||
|
import './Logs.css';
|
||||||
|
|
||||||
const INITIAL_REQUEST = true;
|
const INITIAL_REQUEST = true;
|
||||||
const INITIAL_REQUEST_DATA = ['', TABLE_FIRST_PAGE, INITIAL_REQUEST];
|
const INITIAL_REQUEST_DATA = ['', TABLE_FIRST_PAGE, INITIAL_REQUEST];
|
||||||
|
@ -32,7 +32,7 @@ class Dhcp extends Component {
|
|||||||
const {
|
const {
|
||||||
config, check, processingDhcp, processingConfig,
|
config, check, processingDhcp, processingConfig,
|
||||||
} = this.props.dhcp;
|
} = this.props.dhcp;
|
||||||
const otherDhcpFound = check && check.otherServer
|
const otherDhcpFound = check?.otherServer
|
||||||
&& check.otherServer.found === DHCP_STATUS_RESPONSE.YES;
|
&& check.otherServer.found === DHCP_STATUS_RESPONSE.YES;
|
||||||
const filledConfig = Object.keys(config).every((key) => {
|
const filledConfig = Object.keys(config).every((key) => {
|
||||||
if (key === 'enabled' || key === 'icmp_timeout_msec') {
|
if (key === 'enabled' || key === 'icmp_timeout_msec') {
|
||||||
|
@ -4,7 +4,6 @@ import { connect } from 'react-redux';
|
|||||||
import { Field, reduxForm, formValueSelector } from 'redux-form';
|
import { Field, reduxForm, formValueSelector } 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 {
|
import {
|
||||||
renderInputField,
|
renderInputField,
|
||||||
renderRadioField,
|
renderRadioField,
|
||||||
@ -12,7 +11,10 @@ import {
|
|||||||
toNumber,
|
toNumber,
|
||||||
} from '../../../../helpers/form';
|
} from '../../../../helpers/form';
|
||||||
import {
|
import {
|
||||||
validateBiggerOrEqualZeroValue, validateIpv4, validateIpv6, validateRequiredValue,
|
validateBiggerOrEqualZeroValue,
|
||||||
|
validateIpv4,
|
||||||
|
validateIpv6,
|
||||||
|
validateRequiredValue,
|
||||||
} from '../../../../helpers/validators';
|
} from '../../../../helpers/validators';
|
||||||
import { BLOCKING_MODES, FORM_NAME } from '../../../../helpers/constants';
|
import { BLOCKING_MODES, FORM_NAME } from '../../../../helpers/constants';
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ import './Toast.css';
|
|||||||
|
|
||||||
const Toasts = (props) => (
|
const Toasts = (props) => (
|
||||||
<TransitionGroup className="toasts">
|
<TransitionGroup className="toasts">
|
||||||
{props.toasts.notices && props.toasts.notices.map((toast) => {
|
{props.toasts.notices?.map((toast) => {
|
||||||
const { id } = toast;
|
const { id } = toast;
|
||||||
return (
|
return (
|
||||||
<CSSTransition
|
<CSSTransition
|
||||||
|
@ -120,7 +120,7 @@ const renderDnsPrivacyList = ({ title, list }) => <div className="tab__paragraph
|
|||||||
<strong><Trans>{title}</Trans></strong>
|
<strong><Trans>{title}</Trans></strong>
|
||||||
<ul>{list.map(({ label, components }) => <li key={label}>
|
<ul>{list.map(({ label, components }) => <li key={label}>
|
||||||
<Trans
|
<Trans
|
||||||
components={components && components.map((props) => {
|
components={components?.map((props) => {
|
||||||
if (React.isValidElement(props)) {
|
if (React.isValidElement(props)) {
|
||||||
return props;
|
return props;
|
||||||
}
|
}
|
||||||
@ -198,7 +198,7 @@ const getTabs = ({
|
|||||||
// eslint-disable-next-line react/display-name
|
// eslint-disable-next-line react/display-name
|
||||||
getTitle: () => <div label="dns_privacy" title={t('dns_privacy')}>
|
getTitle: () => <div label="dns_privacy" title={t('dns_privacy')}>
|
||||||
<div className="tab__text">
|
<div className="tab__text">
|
||||||
{tlsAddress && tlsAddress.length > 0 && (
|
{tlsAddress?.length > 0 && (
|
||||||
<div className="tab__paragraph">
|
<div className="tab__paragraph">
|
||||||
<Trans
|
<Trans
|
||||||
values={{ address: tlsAddress[0] }}
|
values={{ address: tlsAddress[0] }}
|
||||||
@ -211,7 +211,7 @@ const getTabs = ({
|
|||||||
</Trans>
|
</Trans>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{httpsAddress && httpsAddress.length > 0 && (
|
{httpsAddress?.length > 0 && (
|
||||||
<div className="tab__paragraph">
|
<div className="tab__paragraph">
|
||||||
<Trans
|
<Trans
|
||||||
values={{ address: httpsAddress[0] }}
|
values={{ address: httpsAddress[0] }}
|
||||||
|
@ -9,6 +9,11 @@
|
|||||||
height: 1.5rem;
|
height: 1.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.icon--smallest {
|
||||||
|
width: 1.2rem;
|
||||||
|
height: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
.icon--gray {
|
.icon--gray {
|
||||||
color: var(--gray-a5);
|
color: var(--gray-a5);
|
||||||
}
|
}
|
||||||
|
@ -175,7 +175,7 @@ export const renderSelectField = ({
|
|||||||
</label>
|
</label>
|
||||||
{!disabled
|
{!disabled
|
||||||
&& touched
|
&& touched
|
||||||
&& (error && <span className="form__message form__message--error">{error}</span>)}
|
&& error && <span className="form__message form__message--error">{error}</span>}
|
||||||
</Fragment>;
|
</Fragment>;
|
||||||
|
|
||||||
renderSelectField.propTypes = {
|
renderSelectField.propTypes = {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import React, { Fragment } from 'react';
|
import React from 'react';
|
||||||
import { normalizeWhois } from './helpers';
|
import { normalizeWhois } from './helpers';
|
||||||
import { WHOIS_ICONS } from './constants';
|
import { WHOIS_ICONS } from './constants';
|
||||||
|
|
||||||
@ -11,12 +11,12 @@ const getFormattedWhois = (whois, t) => {
|
|||||||
return (
|
return (
|
||||||
<span className="logs__whois text-muted" key={key} title={t(key)}>
|
<span className="logs__whois text-muted" key={key} title={t(key)}>
|
||||||
{icon && (
|
{icon && (
|
||||||
<Fragment>
|
<>
|
||||||
<svg className="logs__whois-icon icons">
|
<svg className="logs__whois-icon icons">
|
||||||
<use xlinkHref={`#${icon}`} />
|
<use xlinkHref={`#${icon}`} />
|
||||||
</svg>
|
</svg>
|
||||||
|
|
||||||
</Fragment>
|
</>
|
||||||
)}{whoisInfo[key]}
|
)}{whoisInfo[key]}
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
|
@ -142,7 +142,7 @@ export const addClientInfo = (data, clients, param) => (
|
|||||||
const info = clients.find((item) => item[clientIp]) || '';
|
const info = clients.find((item) => item[clientIp]) || '';
|
||||||
return {
|
return {
|
||||||
...row,
|
...row,
|
||||||
info: (info && info[clientIp]) || '',
|
info: info?.[clientIp] ?? '',
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
@ -342,7 +342,7 @@ export const normalizeTopClients = (topClients) => topClients.reduce(
|
|||||||
|
|
||||||
export const getClientInfo = (clients, ip) => {
|
export const getClientInfo = (clients, ip) => {
|
||||||
const client = clients
|
const client = clients
|
||||||
.find((item) => item.ip_addrs && item.ip_addrs.find((clientIp) => clientIp === ip));
|
.find((item) => item.ip_addrs?.find((clientIp) => clientIp === ip));
|
||||||
|
|
||||||
if (!client) {
|
if (!client) {
|
||||||
return '';
|
return '';
|
||||||
@ -403,7 +403,7 @@ export const secondsToMilliseconds = (seconds) => {
|
|||||||
return seconds;
|
return seconds;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const normalizeRulesTextarea = (text) => text && text.replace(/^\n/g, '')
|
export const normalizeRulesTextarea = (text) => text?.replace(/^\n/g, '')
|
||||||
.replace(/\n\s*\n/g, '\n');
|
.replace(/\n\s*\n/g, '\n');
|
||||||
|
|
||||||
export const isVersionGreater = (currentVersion, previousVersion) => (
|
export const isVersionGreater = (currentVersion, previousVersion) => (
|
||||||
@ -415,7 +415,7 @@ export const normalizeWhois = (whois) => {
|
|||||||
const {
|
const {
|
||||||
city, country, ...values
|
city, country, ...values
|
||||||
} = whois;
|
} = whois;
|
||||||
let location = (country && country) || '';
|
let location = country || '';
|
||||||
|
|
||||||
if (city && location) {
|
if (city && location) {
|
||||||
location = `${location}, ${city}`;
|
location = `${location}, ${city}`;
|
||||||
@ -483,7 +483,7 @@ export const checkParental = (reason) => reason === FILTERED_STATUS.FILTERED_PAR
|
|||||||
export const checkBlockedService = (reason) => reason === FILTERED_STATUS.FILTERED_BLOCKED_SERVICE;
|
export const checkBlockedService = (reason) => reason === FILTERED_STATUS.FILTERED_BLOCKED_SERVICE;
|
||||||
|
|
||||||
export const getCurrentFilter = (url, filters) => {
|
export const getCurrentFilter = (url, filters) => {
|
||||||
const filter = filters && filters.find((item) => url === item.url);
|
const filter = filters?.find((item) => url === item.url);
|
||||||
|
|
||||||
if (filter) {
|
if (filter) {
|
||||||
const { enabled, name, url } = filter;
|
const { enabled, name, url } = filter;
|
||||||
|
@ -28,9 +28,9 @@ const renderInterfaces = ((interfaces) => (
|
|||||||
flags,
|
flags,
|
||||||
} = option;
|
} = option;
|
||||||
|
|
||||||
if (option && ip_addresses && ip_addresses.length > 0) {
|
if (option && ip_addresses?.length > 0) {
|
||||||
const ip = getInterfaceIp(option);
|
const ip = getInterfaceIp(option);
|
||||||
const isDown = flags && flags.includes('down');
|
const isDown = flags?.includes('down');
|
||||||
|
|
||||||
if (isDown) {
|
if (isDown) {
|
||||||
return (
|
return (
|
||||||
|
@ -14,9 +14,9 @@ const access = handleActions(
|
|||||||
} = payload;
|
} = payload;
|
||||||
const newState = {
|
const newState = {
|
||||||
...state,
|
...state,
|
||||||
allowed_clients: (allowed_clients && allowed_clients.join('\n')) || '',
|
allowed_clients: allowed_clients?.join('\n') || '',
|
||||||
disallowed_clients: (disallowed_clients && disallowed_clients.join('\n')) || '',
|
disallowed_clients: disallowed_clients?.join('\n') || '',
|
||||||
blocked_hosts: (blocked_hosts && blocked_hosts.join('\n')) || '',
|
blocked_hosts: blocked_hosts?.join('\n') || '',
|
||||||
processing: false,
|
processing: false,
|
||||||
};
|
};
|
||||||
return newState;
|
return newState;
|
||||||
@ -42,9 +42,9 @@ const access = handleActions(
|
|||||||
} = payload;
|
} = payload;
|
||||||
const newState = {
|
const newState = {
|
||||||
...state,
|
...state,
|
||||||
allowed_clients: (allowed_clients && allowed_clients.join('\n')) || '',
|
allowed_clients: allowed_clients?.join('\n') || '',
|
||||||
disallowed_clients: (disallowed_clients && disallowed_clients.join('\n')) || '',
|
disallowed_clients: disallowed_clients?.join('\n') || '',
|
||||||
blocked_hosts: (blocked_hosts && blocked_hosts.join('\n')) || '',
|
blocked_hosts: blocked_hosts?.join('\n') || '',
|
||||||
processingSet: false,
|
processingSet: false,
|
||||||
};
|
};
|
||||||
return newState;
|
return newState;
|
||||||
|
20
home/auth.go
20
home/auth.go
@ -365,6 +365,7 @@ func parseCookie(cookie string) string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// nolint(gocyclo)
|
||||||
func optionalAuth(handler func(http.ResponseWriter, *http.Request)) func(http.ResponseWriter, *http.Request) {
|
func optionalAuth(handler func(http.ResponseWriter, *http.Request)) func(http.ResponseWriter, *http.Request) {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
@ -391,7 +392,11 @@ func optionalAuth(handler func(http.ResponseWriter, *http.Request)) func(http.Re
|
|||||||
// redirect to login page if not authenticated
|
// redirect to login page if not authenticated
|
||||||
ok := false
|
ok := false
|
||||||
cookie, err := r.Cookie(sessionCookieName)
|
cookie, err := r.Cookie(sessionCookieName)
|
||||||
if err == nil {
|
|
||||||
|
if glProcessCookie(r) {
|
||||||
|
log.Debug("Auth: authentification was handled by GL-Inet submodule")
|
||||||
|
|
||||||
|
} else if err == nil {
|
||||||
r := Context.auth.CheckSession(cookie.Value)
|
r := Context.auth.CheckSession(cookie.Value)
|
||||||
if r == 0 {
|
if r == 0 {
|
||||||
ok = true
|
ok = true
|
||||||
@ -412,8 +417,13 @@ func optionalAuth(handler func(http.ResponseWriter, *http.Request)) func(http.Re
|
|||||||
}
|
}
|
||||||
if !ok {
|
if !ok {
|
||||||
if r.URL.Path == "/" || r.URL.Path == "/index.html" {
|
if r.URL.Path == "/" || r.URL.Path == "/index.html" {
|
||||||
w.Header().Set("Location", "/login.html")
|
if glProcessRedirect(w, r) {
|
||||||
w.WriteHeader(http.StatusFound)
|
log.Debug("Auth: redirected to login page by GL-Inet submodule")
|
||||||
|
|
||||||
|
} else {
|
||||||
|
w.Header().Set("Location", "/login.html")
|
||||||
|
w.WriteHeader(http.StatusFound)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
w.WriteHeader(http.StatusForbidden)
|
w.WriteHeader(http.StatusForbidden)
|
||||||
_, _ = w.Write([]byte("Forbidden"))
|
_, _ = w.Write([]byte("Forbidden"))
|
||||||
@ -510,6 +520,10 @@ func (a *Auth) GetUsers() []User {
|
|||||||
|
|
||||||
// AuthRequired - if authentication is required
|
// AuthRequired - if authentication is required
|
||||||
func (a *Auth) AuthRequired() bool {
|
func (a *Auth) AuthRequired() bool {
|
||||||
|
if GLMode {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
a.lock.Lock()
|
a.lock.Lock()
|
||||||
r := (len(a.users) != 0)
|
r := (len(a.users) != 0)
|
||||||
a.lock.Unlock()
|
a.lock.Unlock()
|
||||||
|
102
home/auth_glinet.go
Normal file
102
home/auth_glinet.go
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
package home
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/binary"
|
||||||
|
"io/ioutil"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/AdguardTeam/golibs/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GLMode - enable GL-Inet compatibility mode
|
||||||
|
var GLMode bool
|
||||||
|
|
||||||
|
var glFilePrefix = "/tmp/gl_token_"
|
||||||
|
|
||||||
|
const glTokenTimeoutSeconds = 3600
|
||||||
|
const glCookieName = "Admin-Token"
|
||||||
|
|
||||||
|
func glProcessRedirect(w http.ResponseWriter, r *http.Request) bool {
|
||||||
|
if !GLMode {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
// redirect to gl-inet login
|
||||||
|
host, _, _ := net.SplitHostPort(r.Host)
|
||||||
|
url := "http://" + host
|
||||||
|
log.Debug("Auth: redirecting to %s", url)
|
||||||
|
http.Redirect(w, r, url, http.StatusFound)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func glProcessCookie(r *http.Request) bool {
|
||||||
|
if !GLMode {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
glCookie, glerr := r.Cookie(glCookieName)
|
||||||
|
if glerr != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Debug("Auth: GL cookie value: %s", glCookie.Value)
|
||||||
|
if glCheckToken(glCookie.Value) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
log.Info("Auth: invalid GL cookie value: %s", glCookie)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func glCheckToken(sess string) bool {
|
||||||
|
tokenName := glFilePrefix + sess
|
||||||
|
_, err := os.Stat(tokenName)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("os.Stat: %s", err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
tokenDate := glGetTokenDate(tokenName)
|
||||||
|
now := uint32(time.Now().UTC().Unix())
|
||||||
|
return now <= (tokenDate + glTokenTimeoutSeconds)
|
||||||
|
}
|
||||||
|
|
||||||
|
func archIsLittleEndian() bool {
|
||||||
|
var i int32 = 0x01020304
|
||||||
|
u := unsafe.Pointer(&i)
|
||||||
|
pb := (*byte)(u)
|
||||||
|
b := *pb
|
||||||
|
return (b == 0x04)
|
||||||
|
}
|
||||||
|
|
||||||
|
func glGetTokenDate(file string) uint32 {
|
||||||
|
f, err := os.Open(file)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("os.Open: %s", err)
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
var dateToken uint32
|
||||||
|
bs, err := ioutil.ReadAll(f)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("ioutil.ReadAll: %s", err)
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
buf := bytes.NewBuffer(bs)
|
||||||
|
|
||||||
|
if archIsLittleEndian() {
|
||||||
|
err := binary.Read(buf, binary.LittleEndian, &dateToken)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("binary.Read: %s", err)
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
err := binary.Read(buf, binary.BigEndian, &dateToken)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("binary.Read: %s", err)
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dateToken
|
||||||
|
}
|
43
home/auth_glinet_test.go
Normal file
43
home/auth_glinet_test.go
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
package home
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAuthGL(t *testing.T) {
|
||||||
|
dir := prepareTestDir()
|
||||||
|
defer func() { _ = os.RemoveAll(dir) }()
|
||||||
|
|
||||||
|
GLMode = true
|
||||||
|
glFilePrefix = dir + "/gl_token_"
|
||||||
|
|
||||||
|
tval := uint32(1)
|
||||||
|
data := make([]byte, 4)
|
||||||
|
if archIsLittleEndian() {
|
||||||
|
binary.LittleEndian.PutUint32(data, tval)
|
||||||
|
} else {
|
||||||
|
binary.BigEndian.PutUint32(data, tval)
|
||||||
|
}
|
||||||
|
assert.Nil(t, ioutil.WriteFile(glFilePrefix+"test", data, 0644))
|
||||||
|
assert.False(t, glCheckToken("test"))
|
||||||
|
|
||||||
|
tval = uint32(time.Now().UTC().Unix() + 60)
|
||||||
|
data = make([]byte, 4)
|
||||||
|
if archIsLittleEndian() {
|
||||||
|
binary.LittleEndian.PutUint32(data, tval)
|
||||||
|
} else {
|
||||||
|
binary.BigEndian.PutUint32(data, tval)
|
||||||
|
}
|
||||||
|
assert.Nil(t, ioutil.WriteFile(glFilePrefix+"test", data, 0644))
|
||||||
|
r, _ := http.NewRequest("GET", "http://localhost/", nil)
|
||||||
|
r.AddCookie(&http.Cookie{Name: glCookieName, Value: "test"})
|
||||||
|
assert.True(t, glProcessCookie(r))
|
||||||
|
GLMode = false
|
||||||
|
}
|
@ -263,6 +263,7 @@ func run(args options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sessFilename := filepath.Join(Context.getDataDir(), "sessions.db")
|
sessFilename := filepath.Join(Context.getDataDir(), "sessions.db")
|
||||||
|
GLMode = args.glinetMode
|
||||||
Context.auth = InitAuth(sessFilename, config.Users, config.WebSessionTTLHours*60*60)
|
Context.auth = InitAuth(sessFilename, config.Users, config.WebSessionTTLHours*60*60)
|
||||||
if Context.auth == nil {
|
if Context.auth == nil {
|
||||||
log.Fatalf("Couldn't initialize Auth module")
|
log.Fatalf("Couldn't initialize Auth module")
|
||||||
@ -525,6 +526,8 @@ type options struct {
|
|||||||
|
|
||||||
// runningAsService flag is set to true when options are passed from the service runner
|
// runningAsService flag is set to true when options are passed from the service runner
|
||||||
runningAsService bool
|
runningAsService bool
|
||||||
|
|
||||||
|
glinetMode bool // Activate GL-Inet mode
|
||||||
}
|
}
|
||||||
|
|
||||||
// loadOptions reads command line arguments and initializes configuration
|
// loadOptions reads command line arguments and initializes configuration
|
||||||
@ -559,6 +562,7 @@ func loadOptions() options {
|
|||||||
{"check-config", "", "Check configuration and exit", nil, func() { o.checkConfig = true }},
|
{"check-config", "", "Check configuration and exit", nil, func() { o.checkConfig = true }},
|
||||||
{"no-check-update", "", "Don't check for updates", nil, func() { o.disableUpdate = true }},
|
{"no-check-update", "", "Don't check for updates", nil, func() { o.disableUpdate = true }},
|
||||||
{"verbose", "v", "Enable verbose output", nil, func() { o.verbose = true }},
|
{"verbose", "v", "Enable verbose output", nil, func() { o.verbose = true }},
|
||||||
|
{"glinet", "", "Run in GL-Inet compatibility mode", nil, func() { o.glinetMode = true }},
|
||||||
{"version", "", "Show the version and exit", nil, func() {
|
{"version", "", "Show the version and exit", nil, func() {
|
||||||
fmt.Printf("AdGuardHome %s\n", versionString)
|
fmt.Printf("AdGuardHome %s\n", versionString)
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
|
Loading…
Reference in New Issue
Block a user