From df61741f605c7d0551047ddf03dfc14f0b39f8e5 Mon Sep 17 00:00:00 2001 From: Dimitry Kolyshev Date: Thu, 23 Mar 2023 15:25:58 +0300 Subject: [PATCH] Pull request: 1163 safesearch http api vol.3 Merge in DNS/adguard-home from 1163-safesearch-1-3 to master Squashed commit of the following: commit f26c5fb4f7a27dc61b10c28d6672d5307796784c Merge: e7a1b885 143616ca Author: Dimitry Kolyshev Date: Thu Mar 23 18:45:25 2023 +0700 Merge remote-tracking branch 'origin/master' into 1163-safesearch-1-3 # Conflicts: # CHANGELOG.md commit e7a1b885d67628c187ce08327338cf3138012f03 Merge: 01b73d76 eb5d8a49 Author: Vladislav Abdulmyanov Date: Wed Mar 22 13:55:23 2023 +0200 Merge branch '1163-safesearch-1-3' of ssh://bit.adguard.com:7999/dns/adguard-home into 1163-safesearch-1-3 commit 01b73d763c6ee76de995093cc7107f113c7785ce Author: Vladislav Abdulmyanov Date: Wed Mar 22 13:52:02 2023 +0200 client: add safe search extended settings to clients commit eb5d8a499ac1036e5077d2b4aa84479381577e10 Author: Dimitry Kolyshev Date: Wed Mar 22 18:50:23 2023 +0700 all: docs commit 2043a8fba7f664ef365ccc5abac14a85035eb4b7 Author: Dimitry Kolyshev Date: Wed Mar 22 09:42:50 2023 +0700 all: docs commit bb1d2f6c0252891ccac3d3727eb23288a24d4bda Merge: 95f9fd3d c3edab43 Author: Dimitry Kolyshev Date: Wed Mar 22 09:42:00 2023 +0700 Merge remote-tracking branch 'origin/master' into 1163-safesearch-1-3 commit 95f9fd3dd1e8abcdf1a156e81aff8e52f320f4c3 Author: Vladislav Abdulmyanov Date: Tue Mar 21 15:25:39 2023 +0200 client: move to new safe search api commit ac823a911f0d6ab6f1813d11a0ca082d54cc9131 Author: Dimitry Kolyshev Date: Mon Mar 20 22:40:29 2023 +0700 all: docs commit aaa287b125c7c7a775b821e0dd272199229a7538 Merge: 16fa7031 48431f8b Author: Dimitry Kolyshev Date: Mon Mar 20 22:39:14 2023 +0700 Merge remote-tracking branch 'origin/master' into 1163-safesearch-1-3 commit 16fa7031ab2aec31139ace54ffa0155cde8e9135 Author: Dimitry Kolyshev Date: Mon Mar 20 22:39:03 2023 +0700 all: docs commit 498f7d3cbb842eda218b0fd06fc3bb3601b81f80 Author: Dimitry Kolyshev Date: Mon Mar 20 18:59:47 2023 +0700 filtering: imp code commit aab7b70e2355ba86577e5156c1d5569b21b4b358 Author: Dimitry Kolyshev Date: Mon Mar 20 18:40:18 2023 +0700 filtering: imp code commit d2870a18ffdb1d293993487073912168d6b75a38 Author: Dimitry Kolyshev Date: Fri Mar 17 21:57:58 2023 +0700 filtering: imp code commit 868f5d1ed29c3af702114079e7ffe46e136eb901 Author: Dimitry Kolyshev Date: Fri Mar 17 19:06:36 2023 +0700 all: imp docs commit f6d70b06ed873684501ce17f647ccf07a85dd50b Author: Dimitry Kolyshev Date: Fri Mar 17 19:05:40 2023 +0700 filtering: imp code commit 7cd9a37dde6262a8cf4f0f13f9946e011cc0e2cf Author: Dimitry Kolyshev Date: Thu Mar 16 14:56:51 2023 +0700 home: imp code commit 84d8817512e47a517ed2880ffa9dde5ffda1d288 Author: Dimitry Kolyshev Date: Thu Mar 16 09:39:41 2023 +0700 all: safesearch http api --- CHANGELOG.md | 13 +++- client/src/__locales/en.json | 1 + client/src/actions/index.js | 25 +++---- client/src/api/Api.js | 36 +++++++--- .../Clients/ClientsTable/ClientsTable.js | 6 ++ .../src/components/Settings/Clients/Form.js | 33 +++++++-- client/src/components/Settings/index.js | 40 ++++++++--- client/src/components/ui/Checkbox.js | 4 +- client/src/reducers/settings.js | 4 +- internal/filtering/http.go | 1 + internal/filtering/safesearch.go | 2 +- internal/filtering/safesearchhttp.go | 48 +++++++++++-- internal/home/clientshttp.go | 62 ++++++++-------- openapi/CHANGELOG.md | 72 +++++++++++++++++++ openapi/openapi.yaml | 51 ++++++++++--- 15 files changed, 315 insertions(+), 83 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 39f44fc1..a8f44577 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,7 +36,7 @@ NOTE: Add new changes BELOW THIS COMMENT. - The ability to manage safesearch for each service by using the new `safe_search` field ([#1163]). -### Changed +### Changed - ARPA domain names containing a subnet within private networks now also considered private, behaving closer to [RFC 6761][rfc6761] ([#5567]). @@ -90,6 +90,17 @@ In this release, the schema version has changed from 17 to 20. ### Deprecated +- The `POST /control/safesearch/enable` HTTP API is deprecated. Use the new + `PUT /control/safesearch/settings` API. +- The `POST /control/safesearch/disable` HTTP API is deprecated. Use the new + `PUT /control/safesearch/settings` API +- The `safesearch_enabled` field is deprecated in the following HTTP APIs: + - `GET /control/clients` + - `POST /control/clients/add` + - `POST /control/clients/update` + - `GET /control/clients/find?ip0=...&ip1=...&ip2=...` + + Check `openapi/openapi.yaml` for more details. - The `GET /control/stats_info` HTTP API; use the new `GET /control/stats/config` API instead. diff --git a/client/src/__locales/en.json b/client/src/__locales/en.json index 902fc4d3..08f3c08f 100644 --- a/client/src/__locales/en.json +++ b/client/src/__locales/en.json @@ -167,6 +167,7 @@ "enabled_parental_toast": "Enabled Parental Control", "disabled_safe_search_toast": "Disabled Safe Search", "enabled_save_search_toast": "Enabled Safe Search", + "updated_save_search_toast": "Safe Search settings updated", "enabled_table_header": "Enabled", "name_table_header": "Name", "list_url_table_header": "List URL", diff --git a/client/src/actions/index.js b/client/src/actions/index.js index 2780c94d..a164f51a 100644 --- a/client/src/actions/index.js +++ b/client/src/actions/index.js @@ -24,6 +24,12 @@ import { getFilteringStatus, setRules } from './filtering'; export const toggleSettingStatus = createAction('SETTING_STATUS_TOGGLE'); export const showSettingsFailure = createAction('SETTINGS_FAILURE_SHOW'); +/** + * + * @param {*} settingKey = SETTINGS_NAMES + * @param {*} status: boolean | SafeSearchConfig + * @returns + */ export const toggleSetting = (settingKey, status) => async (dispatch) => { let successMessage = ''; try { @@ -49,14 +55,9 @@ export const toggleSetting = (settingKey, status) => async (dispatch) => { dispatch(toggleSettingStatus({ settingKey })); break; case SETTINGS_NAMES.safesearch: - if (status) { - successMessage = 'disabled_safe_search_toast'; - await apiClient.disableSafesearch(); - } else { - successMessage = 'enabled_save_search_toast'; - await apiClient.enableSafesearch(); - } - dispatch(toggleSettingStatus({ settingKey })); + successMessage = 'updated_save_search_toast'; + await apiClient.updateSafesearch(status); + dispatch(toggleSettingStatus({ settingKey, value: status })); break; default: break; @@ -71,7 +72,9 @@ export const initSettingsRequest = createAction('SETTINGS_INIT_REQUEST'); export const initSettingsFailure = createAction('SETTINGS_INIT_FAILURE'); export const initSettingsSuccess = createAction('SETTINGS_INIT_SUCCESS'); -export const initSettings = (settingsList) => async (dispatch) => { +export const initSettings = (settingsList = { + safebrowsing: {}, parental: {}, +}) => async (dispatch) => { dispatch(initSettingsRequest()); try { const safebrowsingStatus = await apiClient.getSafebrowsingStatus(); @@ -80,7 +83,6 @@ export const initSettings = (settingsList) => async (dispatch) => { const { safebrowsing, parental, - safesearch, } = settingsList; const newSettingsList = { safebrowsing: { @@ -92,8 +94,7 @@ export const initSettings = (settingsList) => async (dispatch) => { enabled: parentalStatus.enabled, }, safesearch: { - ...safesearch, - enabled: safesearchStatus.enabled, + ...safesearchStatus, }, }; dispatch(initSettingsSuccess({ settingsList: newSettingsList })); diff --git a/client/src/api/Api.js b/client/src/api/Api.js index 60f1faad..caf836b8 100644 --- a/client/src/api/Api.js +++ b/client/src/api/Api.js @@ -208,24 +208,40 @@ class Api { // Safesearch SAFESEARCH_STATUS = { path: 'safesearch/status', method: 'GET' }; - SAFESEARCH_ENABLE = { path: 'safesearch/enable', method: 'POST' }; - - SAFESEARCH_DISABLE = { path: 'safesearch/disable', method: 'POST' }; + SAFESEARCH_UPDATE = { path: 'safesearch/settings', method: 'PUT' }; getSafesearchStatus() { const { path, method } = this.SAFESEARCH_STATUS; return this.makeRequest(path, method); } - enableSafesearch() { - const { path, method } = this.SAFESEARCH_ENABLE; - return this.makeRequest(path, method); + /** + * interface SafeSearchConfig { + "enabled": boolean, + "bing": boolean, + "duckduckgo": boolean, + "google": boolean, + "pixabay": boolean, + "yandex": boolean, + "youtube": boolean + * } + * @param {*} data - SafeSearchConfig + * @returns 200 ok + */ + updateSafesearch(data) { + const { path, method } = this.SAFESEARCH_UPDATE; + return this.makeRequest(path, method, { data }); } - disableSafesearch() { - const { path, method } = this.SAFESEARCH_DISABLE; - return this.makeRequest(path, method); - } + // enableSafesearch() { + // const { path, method } = this.SAFESEARCH_ENABLE; + // return this.makeRequest(path, method); + // } + + // disableSafesearch() { + // const { path, method } = this.SAFESEARCH_DISABLE; + // return this.makeRequest(path, method); + // } // Language diff --git a/client/src/components/Settings/Clients/ClientsTable/ClientsTable.js b/client/src/components/Settings/Clients/ClientsTable/ClientsTable.js index 2d2b893b..41ed4e3b 100644 --- a/client/src/components/Settings/Clients/ClientsTable/ClientsTable.js +++ b/client/src/components/Settings/Clients/ClientsTable/ClientsTable.js @@ -7,6 +7,7 @@ import { useDispatch, useSelector } from 'react-redux'; import ReactTable from 'react-table'; import { getAllBlockedServices } from '../../../../actions/services'; +import { initSettings } from '../../../../actions'; import { splitByNewLine, countClientsStatistics, @@ -38,9 +39,13 @@ const ClientsTable = ({ const [t] = useTranslation(); const dispatch = useDispatch(); const services = useSelector((store) => store?.services); + const globalSettings = useSelector((store) => store?.settings.settingsList) || {}; + + const { safesearch } = globalSettings; useEffect(() => { dispatch(getAllBlockedServices()); + dispatch(initSettings()); }, []); const handleFormAdd = (values) => { @@ -107,6 +112,7 @@ const ClientsTable = ({ tags: [], use_global_settings: true, use_global_blocked_services: true, + safe_search: { ...(safesearch || {}) }, }; }; diff --git a/client/src/components/Settings/Clients/Form.js b/client/src/components/Settings/Clients/Form.js index f6b12d1c..6e5763e6 100644 --- a/client/src/components/Settings/Clients/Form.js +++ b/client/src/components/Settings/Clients/Form.js @@ -11,7 +11,7 @@ import Select from 'react-select'; import i18n from '../../../i18n'; import Tabs from '../../ui/Tabs'; import Examples from '../Dns/Upstream/Examples'; -import { toggleAllServices, trimLinesAndRemoveEmpty } from '../../../helpers/helpers'; +import { toggleAllServices, trimLinesAndRemoveEmpty, captitalizeWords } from '../../../helpers/helpers'; import { renderInputField, renderGroupField, @@ -40,10 +40,6 @@ const settingsCheckboxes = [ name: 'parental_enabled', placeholder: 'use_adguard_parental', }, - { - name: 'safesearch_enabled', - placeholder: 'enforce_safe_search', - }, ]; const validate = (values) => { const errors = {}; @@ -139,8 +135,12 @@ let Form = (props) => { processingUpdating, invalid, tagsOptions, + initialValues, } = props; const services = useSelector((store) => store?.services); + const { safe_search } = initialValues; + const safeSearchServices = { ...safe_search }; + delete safeSearchServices.enabled; const [activeTabLabel, setActiveTabLabel] = useState('settings'); @@ -163,6 +163,28 @@ let Form = (props) => { /> ))} +
+ +
+
+ {Object.keys(safeSearchServices).map((searchKey) => ( +
+ +
+ ))} +
, }, block_services: { @@ -358,6 +380,7 @@ Form.propTypes = { processingUpdating: PropTypes.bool.isRequired, invalid: PropTypes.bool.isRequired, tagsOptions: PropTypes.array.isRequired, + initialValues: PropTypes.object, }; const selector = formValueSelector(FORM_NAME.CLIENT); diff --git a/client/src/components/Settings/index.js b/client/src/components/Settings/index.js index f4e191c3..43aff62e 100644 --- a/client/src/components/Settings/index.js +++ b/client/src/components/Settings/index.js @@ -10,7 +10,7 @@ import Checkbox from '../ui/Checkbox'; import Loading from '../ui/Loading'; import PageTitle from '../ui/PageTitle'; import Card from '../ui/Card'; -import { getObjectKeysSorted } from '../../helpers/helpers'; +import { getObjectKeysSorted, captitalizeWords } from '../../helpers/helpers'; import './Settings.css'; const ORDER_KEY = 'order'; @@ -28,12 +28,6 @@ const SETTINGS = { subtitle: 'use_adguard_parental_hint', [ORDER_KEY]: 1, }, - safesearch: { - enabled: false, - title: 'enforce_safe_search', - subtitle: 'enforce_save_search_hint', - [ORDER_KEY]: 2, - }, }; class Settings extends Component { @@ -44,7 +38,7 @@ class Settings extends Component { this.props.getFilteringStatus(); } - renderSettings = (settings) => getObjectKeysSorted(settings, ORDER_KEY) + renderSettings = (settings) => getObjectKeysSorted(SETTINGS, ORDER_KEY) .map((key) => { const setting = settings[key]; const { enabled } = setting; @@ -55,6 +49,35 @@ class Settings extends Component { />; }); + renderSafeSearch = () => { + const { settings: { settingsList: { safesearch } } } = this.props; + const { enabled } = safesearch || {}; + const searches = { ...(safesearch || {}) }; + delete searches.enabled; + return ( + <> + this.props.toggleSetting('safesearch', { ...safesearch, enabled })} + /> +
+ {Object.keys(searches).map((searchKey) => ( + this.props.toggleSetting('safesearch', { ...safesearch, [searchKey]: checked })} + /> + ))} +
+ + ); + }; + render() { const { settings, @@ -92,6 +115,7 @@ class Settings extends Component { setFiltersConfig={setFiltersConfig} /> {this.renderSettings(settings.settingsList)} + {this.renderSafeSearch()} diff --git a/client/src/components/ui/Checkbox.js b/client/src/components/ui/Checkbox.js index ce5b990a..2079cdb9 100644 --- a/client/src/components/ui/Checkbox.js +++ b/client/src/components/ui/Checkbox.js @@ -11,13 +11,14 @@ class Checkbox extends Component { subtitle, enabled, handleChange, + disabled, t, } = this.props; return (