From a5c2ad1b2fa52a071beb759d6b673de73a3d4f4d Mon Sep 17 00:00:00 2001 From: Ildar Kamalov Date: Tue, 4 Feb 2020 15:48:07 +0300 Subject: [PATCH] Merge: - client: block/unblock client without requesting stats Closes #896 Squashed commit of the following: commit 66b781438aa668a16b19455c3e0dc5100417d869 Author: Ildar Kamalov Date: Mon Feb 3 12:59:25 2020 +0300 - client: block/unblock client without requesting stats commit e70f62738d549e32339bae3d5e996a912b99c21d Author: Ildar Kamalov Date: Mon Feb 3 12:22:13 2020 +0300 - client: get current access settings before set commit 65c59d1d55f3255f33f917b61b6ab2c6c2e54271 Author: Ildar Kamalov Date: Mon Feb 3 12:21:12 2020 +0300 * client: mode svg-url-loader to devDependencies --- client/package-lock.json | 30 ++++++++++++++++------ client/package.json | 4 +-- client/src/actions/access.js | 19 ++++++-------- client/src/actions/stats.js | 7 ++--- client/src/components/Dashboard/Clients.js | 16 +++++++----- client/src/components/Dashboard/index.js | 5 +++- client/src/helpers/helpers.js | 11 -------- client/src/reducers/access.js | 16 +++++++++++- 8 files changed, 63 insertions(+), 45 deletions(-) diff --git a/client/package-lock.json b/client/package-lock.json index e8732e57..0e43676f 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -821,6 +821,7 @@ "version": "6.5.3", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.3.tgz", "integrity": "sha512-LqZ9wY+fx3UMiiPd741yB2pj3hhil+hQc8taf4o2QGRFpWgZ2V5C8HA165DY9sS3fJwsk7uT7ZlFEyC3Ig3lLg==", + "dev": true, "requires": { "fast-deep-equal": "^2.0.1", "fast-json-stable-stringify": "^2.0.0", @@ -837,7 +838,8 @@ "ajv-keywords": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.2.0.tgz", - "integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo=" + "integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo=", + "dev": true }, "align-text": { "version": "0.1.4", @@ -2278,7 +2280,8 @@ "big.js": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", - "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==" + "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==", + "dev": true }, "binary-extensions": { "version": "1.11.0", @@ -4218,7 +4221,8 @@ "emojis-list": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", - "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=" + "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=", + "dev": true }, "encodeurl": { "version": "1.0.2", @@ -5231,7 +5235,8 @@ "fast-deep-equal": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", - "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=" + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true }, "fast-glob": { "version": "2.2.6", @@ -5250,7 +5255,8 @@ "fast-json-stable-stringify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", + "dev": true }, "fast-levenshtein": { "version": "2.0.6", @@ -7551,7 +7557,8 @@ "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true }, "json-stable-stringify-without-jsonify": { "version": "1.0.1", @@ -7568,7 +7575,8 @@ "json5": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", - "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=" + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", + "dev": true }, "jsx-ast-utils": { "version": "1.4.1", @@ -7706,6 +7714,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", + "dev": true, "requires": { "big.js": "^3.1.3", "emojis-list": "^2.0.0", @@ -10287,7 +10296,8 @@ "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true }, "q": { "version": "1.5.1", @@ -11137,6 +11147,7 @@ "version": "0.4.7", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.7.tgz", "integrity": "sha512-v/iwU6wvwGK8HbU9yi3/nhGzP0yGSuhQMzL6ySiec1FSrZZDkhm4noOSWzrNFo/jEc+SJY6jRTwuwbSXJPDUnQ==", + "dev": true, "requires": { "ajv": "^6.1.0", "ajv-keywords": "^3.1.0" @@ -12564,6 +12575,7 @@ "version": "2.3.2", "resolved": "https://registry.npmjs.org/svg-url-loader/-/svg-url-loader-2.3.2.tgz", "integrity": "sha1-3YaybBn+O5FPBOoQ7zlZTq3gRGQ=", + "dev": true, "requires": { "file-loader": "1.1.11", "loader-utils": "1.1.0" @@ -12573,6 +12585,7 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-1.1.11.tgz", "integrity": "sha512-TGR4HU7HUsGg6GCOPJnFk06RhWgEWFLAGWiT6rcD+GRC2keU3s9RGJ+b3Z6/U73jwwNb2gKLJ7YCrp+jvU4ALg==", + "dev": true, "requires": { "loader-utils": "^1.0.2", "schema-utils": "^0.4.5" @@ -13044,6 +13057,7 @@ "version": "4.2.2", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "dev": true, "requires": { "punycode": "^2.1.0" } diff --git a/client/package.json b/client/package.json index aadad4b5..4ee1c1c3 100644 --- a/client/package.json +++ b/client/package.json @@ -34,7 +34,6 @@ "redux-actions": "^2.4.0", "redux-form": "^7.4.2", "redux-thunk": "^2.3.0", - "svg-url-loader": "^2.3.2", "url-polyfill": "^1.1.7" }, "devDependencies": { @@ -75,6 +74,7 @@ "url-loader": "^1.0.1", "webpack": "3.8.1", "webpack-dev-server": "^3.1.14", - "webpack-merge": "^4.1.3" + "webpack-merge": "^4.1.3", + "svg-url-loader": "^2.3.2" } } diff --git a/client/src/actions/access.js b/client/src/actions/access.js index 1f51cea7..96c661c1 100644 --- a/client/src/actions/access.js +++ b/client/src/actions/access.js @@ -3,7 +3,6 @@ import { t } from 'i18next'; import apiClient from '../api/Api'; import { addErrorToast, addSuccessToast } from './index'; -import { getStats, getStatsConfig } from './stats'; import { normalizeTextarea } from '../helpers/helpers'; import { ACTION } from '../helpers/constants'; @@ -50,11 +49,13 @@ export const toggleClientBlockRequest = createAction('TOGGLE_CLIENT_BLOCK_REQUES export const toggleClientBlockFailure = createAction('TOGGLE_CLIENT_BLOCK_FAILURE'); export const toggleClientBlockSuccess = createAction('TOGGLE_CLIENT_BLOCK_SUCCESS'); -export const toggleClientBlock = (type, ip) => async (dispatch, getState) => { +export const toggleClientBlock = (type, ip) => async (dispatch) => { dispatch(toggleClientBlockRequest()); try { - const { allowed_clients, disallowed_clients, blocked_hosts } = getState().access; - let updatedDisallowedClients = normalizeTextarea(disallowed_clients); + const { + allowed_clients, disallowed_clients, blocked_hosts, + } = await apiClient.getAccessList(); + let updatedDisallowedClients = disallowed_clients; if (type === ACTION.unblock && updatedDisallowedClients.includes(ip)) { updatedDisallowedClients = updatedDisallowedClients.filter(client => client !== ip); @@ -63,23 +64,19 @@ export const toggleClientBlock = (type, ip) => async (dispatch, getState) => { } const values = { - allowed_clients: normalizeTextarea(allowed_clients), - blocked_hosts: normalizeTextarea(blocked_hosts), + allowed_clients, + blocked_hosts, disallowed_clients: updatedDisallowedClients, }; await apiClient.setAccessList(values); - dispatch(toggleClientBlockSuccess()); + dispatch(toggleClientBlockSuccess(values)); if (type === ACTION.unblock) { dispatch(addSuccessToast(t('client_unblocked', { ip }))); } else if (type === ACTION.block) { dispatch(addSuccessToast(t('client_blocked', { ip }))); } - - dispatch(getStats()); - dispatch(getStatsConfig()); - dispatch(getAccessList()); } catch (error) { dispatch(addErrorToast({ error })); dispatch(toggleClientBlockFailure()); diff --git a/client/src/actions/stats.js b/client/src/actions/stats.js index 7a12b203..25897aab 100644 --- a/client/src/actions/stats.js +++ b/client/src/actions/stats.js @@ -2,7 +2,7 @@ import { createAction } from 'redux-actions'; import apiClient from '../api/Api'; import { addErrorToast, addSuccessToast } from './index'; -import { normalizeTopStats, secondsToMilliseconds, getParamsForClientsSearch, addClientInfo, addClientStatus } from '../helpers/helpers'; +import { normalizeTopStats, secondsToMilliseconds, getParamsForClientsSearch, addClientInfo } from '../helpers/helpers'; export const getStatsConfigRequest = createAction('GET_STATS_CONFIG_REQUEST'); export const getStatsConfigFailure = createAction('GET_STATS_CONFIG_FAILURE'); @@ -46,15 +46,12 @@ export const getStats = () => async (dispatch) => { const normalizedTopClients = normalizeTopStats(stats.top_clients); const clientsParams = getParamsForClientsSearch(normalizedTopClients, 'name'); const clients = await apiClient.findClients(clientsParams); - const accessData = await apiClient.getAccessList(); - const { disallowed_clients } = accessData; const topClientsWithInfo = addClientInfo(normalizedTopClients, clients, 'name'); - const topClientsWithStatus = addClientStatus(topClientsWithInfo, disallowed_clients, 'name'); const normalizedStats = { ...stats, top_blocked_domains: normalizeTopStats(stats.top_blocked_domains), - top_clients: topClientsWithStatus, + top_clients: topClientsWithInfo, top_queried_domains: normalizeTopStats(stats.top_queried_domains), avg_processing_time: secondsToMilliseconds(stats.avg_processing_time), }; diff --git a/client/src/components/Dashboard/Clients.js b/client/src/components/Dashboard/Clients.js index 04c3270b..0a9ec903 100644 --- a/client/src/components/Dashboard/Clients.js +++ b/client/src/components/Dashboard/Clients.js @@ -57,10 +57,12 @@ const renderBlockingButton = (blocked, ip, handleClick, processing) => { ); }; -const clientCell = (t, toggleClientStatus, processing) => +const isBlockedClient = (clients, ip) => !!(clients && clients.includes(ip)); + +const clientCell = (t, toggleClientStatus, processing, disallowedClients) => function cell(row) { - const { original, value } = row; - const { blocked } = original; + const { value } = row; + const blocked = isBlockedClient(disallowedClients, value); return ( @@ -80,6 +82,7 @@ const Clients = ({ dnsQueries, toggleClientStatus, processingAccessSet, + disallowedClients, }) => ( parseInt(a.replace(/\./g, ''), 10) - parseInt(b.replace(/\./g, ''), 10), - Cell: clientCell(t, toggleClientStatus, processingAccessSet), + Cell: clientCell(t, toggleClientStatus, processingAccessSet, disallowedClients), }, { Header: requests_count, @@ -122,9 +125,9 @@ const Clients = ({ return {}; } - const { blocked } = rowInfo.original; + const { ip } = rowInfo.original; - if (blocked) { + if (isBlockedClient(disallowedClients, ip)) { return { className: 'red', }; @@ -148,6 +151,7 @@ Clients.propTypes = { t: PropTypes.func.isRequired, toggleClientStatus: PropTypes.func.isRequired, processingAccessSet: PropTypes.bool.isRequired, + disallowedClients: PropTypes.string.isRequired, }; export default withNamespaces()(Clients); diff --git a/client/src/components/Dashboard/index.js b/client/src/components/Dashboard/index.js index 01ce0448..d5db2388 100644 --- a/client/src/components/Dashboard/index.js +++ b/client/src/components/Dashboard/index.js @@ -19,6 +19,7 @@ class Dashboard extends Component { } getAllStats = () => { + this.props.getAccessList(); this.props.getStats(); this.props.getStatsConfig(); }; @@ -53,7 +54,8 @@ class Dashboard extends Component { dashboard, stats, access, t, } = this.props; const statsProcessing = stats.processingStats - || stats.processingGetConfig; + || stats.processingGetConfig + || access.processing; const subtitle = stats.interval === 1 @@ -130,6 +132,7 @@ class Dashboard extends Component { refreshButton={refreshButton} toggleClientStatus={this.toggleClientStatus} processingAccessSet={access.processingSet} + disallowedClients={access.disallowed_clients} />
diff --git a/client/src/helpers/helpers.js b/client/src/helpers/helpers.js index e748463e..977b0eae 100644 --- a/client/src/helpers/helpers.js +++ b/client/src/helpers/helpers.js @@ -122,17 +122,6 @@ export const addClientInfo = (data, clients, param) => ( }) ); -export const addClientStatus = (data, disallowedClients, param) => ( - data.map((row) => { - const clientIp = row[param]; - const blocked = !!(disallowedClients && disallowedClients.includes(clientIp)); - return { - ...row, - blocked, - }; - }) -); - export const normalizeFilteringStatus = (filteringStatus) => { const { enabled, filters, user_rules: userRules, interval, diff --git a/client/src/reducers/access.js b/client/src/reducers/access.js index 3ff517cf..79110279 100644 --- a/client/src/reducers/access.js +++ b/client/src/reducers/access.js @@ -34,7 +34,21 @@ const access = handleActions( [actions.toggleClientBlockRequest]: state => ({ ...state, processingSet: true }), [actions.toggleClientBlockFailure]: state => ({ ...state, processingSet: false }), - [actions.toggleClientBlockSuccess]: state => ({ ...state, processingSet: false }), + [actions.toggleClientBlockSuccess]: (state, { payload }) => { + const { + allowed_clients, + disallowed_clients, + blocked_hosts, + } = payload; + const newState = { + ...state, + allowed_clients: (allowed_clients && allowed_clients.join('\n')) || '', + disallowed_clients: (disallowed_clients && disallowed_clients.join('\n')) || '', + blocked_hosts: (blocked_hosts && blocked_hosts.join('\n')) || '', + processingSet: false, + }; + return newState; + }, }, { processing: true,