Skip to content

Commit

Permalink
Pull request: 1163 safesearch http api vol.3
Browse files Browse the repository at this point in the history
Merge in DNS/adguard-home from 1163-safesearch-1-3 to master

Squashed commit of the following:

commit f26c5fb
Merge: e7a1b88 143616c
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Thu Mar 23 18:45:25 2023 +0700

    Merge remote-tracking branch 'origin/master' into 1163-safesearch-1-3

    # Conflicts:
    #	CHANGELOG.md

commit e7a1b88
Merge: 01b73d7 eb5d8a4
Author: Vladislav Abdulmyanov <v.abdulmyanov@adguard.com>
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 01b73d7
Author: Vladislav Abdulmyanov <v.abdulmyanov@adguard.com>
Date:   Wed Mar 22 13:52:02 2023 +0200

    client: add safe search extended settings to clients

commit eb5d8a4
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Wed Mar 22 18:50:23 2023 +0700

    all: docs

commit 2043a8f
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Wed Mar 22 09:42:50 2023 +0700

    all: docs

commit bb1d2f6
Merge: 95f9fd3 c3edab4
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Wed Mar 22 09:42:00 2023 +0700

    Merge remote-tracking branch 'origin/master' into 1163-safesearch-1-3

commit 95f9fd3
Author: Vladislav Abdulmyanov <v.abdulmyanov@adguard.com>
Date:   Tue Mar 21 15:25:39 2023 +0200

    client: move to new safe search api

commit ac823a9
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Mon Mar 20 22:40:29 2023 +0700

    all: docs

commit aaa287b
Merge: 16fa703 48431f8
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Mon Mar 20 22:39:14 2023 +0700

    Merge remote-tracking branch 'origin/master' into 1163-safesearch-1-3

commit 16fa703
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Mon Mar 20 22:39:03 2023 +0700

    all: docs

commit 498f7d3
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Mon Mar 20 18:59:47 2023 +0700

    filtering: imp code

commit aab7b70
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Mon Mar 20 18:40:18 2023 +0700

    filtering: imp code

commit d2870a1
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Fri Mar 17 21:57:58 2023 +0700

    filtering: imp code

commit 868f5d1
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Fri Mar 17 19:06:36 2023 +0700

    all: imp docs

commit f6d70b0
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Fri Mar 17 19:05:40 2023 +0700

    filtering: imp code

commit 7cd9a37
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Thu Mar 16 14:56:51 2023 +0700

    home: imp code

commit 84d8817
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Thu Mar 16 09:39:41 2023 +0700

    all: safesearch http api
  • Loading branch information
Mizzick committed Mar 23, 2023
1 parent 143616c commit df61741
Show file tree
Hide file tree
Showing 15 changed files with 318 additions and 86 deletions.
13 changes: 12 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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]).
Expand Down Expand Up @@ -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.

Expand Down
1 change: 1 addition & 0 deletions client/src/__locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
25 changes: 13 additions & 12 deletions client/src/actions/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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;
Expand All @@ -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();
Expand All @@ -80,7 +83,6 @@ export const initSettings = (settingsList) => async (dispatch) => {
const {
safebrowsing,
parental,
safesearch,
} = settingsList;
const newSettingsList = {
safebrowsing: {
Expand All @@ -92,8 +94,7 @@ export const initSettings = (settingsList) => async (dispatch) => {
enabled: parentalStatus.enabled,
},
safesearch: {
...safesearch,
enabled: safesearchStatus.enabled,
...safesearchStatus,
},
};
dispatch(initSettingsSuccess({ settingsList: newSettingsList }));
Expand Down
40 changes: 28 additions & 12 deletions client/src/api/Api.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

disableSafesearch() {
const { path, method } = this.SAFESEARCH_DISABLE;
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 });
}

// 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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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) => {
Expand Down Expand Up @@ -107,6 +112,7 @@ const ClientsTable = ({
tags: [],
use_global_settings: true,
use_global_blocked_services: true,
safe_search: { ...(safesearch || {}) },
};
};

Expand Down
33 changes: 28 additions & 5 deletions client/src/components/Settings/Clients/Form.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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 = {};
Expand Down Expand Up @@ -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');

Expand All @@ -163,6 +163,28 @@ let Form = (props) => {
/>
</div>
))}
<div className="form__group">
<Field
name="safe_search.enabled"
type="checkbox"
component={CheckboxField}
placeholder={t('enforce_safe_search')}
disabled={useGlobalSettings}
/>
</div>
<div className='form__group--inner'>
{Object.keys(safeSearchServices).map((searchKey) => (
<div key={searchKey}>
<Field
name={`safe_search.${searchKey}`}
type="checkbox"
component={CheckboxField}
placeholder={captitalizeWords(searchKey)}
disabled={useGlobalSettings}
/>
</div>
))}
</div>
</div>,
},
block_services: {
Expand Down Expand Up @@ -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);
Expand Down
40 changes: 32 additions & 8 deletions client/src/components/Settings/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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 {
Expand All @@ -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;
Expand All @@ -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 (
<>
<Checkbox
enabled={enabled}
title='enforce_safe_search'
subtitle='enforce_save_search_hint'
handleChange={({ target: { checked: enabled } }) => this.props.toggleSetting('safesearch', { ...safesearch, enabled })}
/>
<div className='form__group--inner'>
{Object.keys(searches).map((searchKey) => (
<Checkbox
key={searchKey}
enabled={searches[searchKey]}
title={captitalizeWords(searchKey)}
subtitle=''
disabled={!safesearch.enabled}
handleChange={({ target: { checked } }) => this.props.toggleSetting('safesearch', { ...safesearch, [searchKey]: checked })}
/>
))}
</div>
</>
);
};

render() {
const {
settings,
Expand Down Expand Up @@ -92,6 +115,7 @@ class Settings extends Component {
setFiltersConfig={setFiltersConfig}
/>
{this.renderSettings(settings.settingsList)}
{this.renderSafeSearch()}
</div>
</Card>
</div>
Expand Down
4 changes: 3 additions & 1 deletion client/src/components/ui/Checkbox.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,14 @@ class Checkbox extends Component {
subtitle,
enabled,
handleChange,
disabled,
t,
} = this.props;
return (
<div className="form__group form__group--checkbox">
<label className="checkbox checkbox--settings">
<span className="checkbox__marker"/>
<input type="checkbox" className="checkbox__input" onChange={handleChange} checked={enabled}/>
<input type="checkbox" className="checkbox__input" onChange={handleChange} checked={enabled} disabled={disabled}/>
<span className="checkbox__label">
<span className="checkbox__label-text">
<span className="checkbox__label-title">{ t(title) }</span>
Expand All @@ -35,6 +36,7 @@ Checkbox.propTypes = {
subtitle: PropTypes.string.isRequired,
enabled: PropTypes.bool.isRequired,
handleChange: PropTypes.func.isRequired,
disabled: PropTypes.bool,
t: PropTypes.func,
};

Expand Down
4 changes: 2 additions & 2 deletions client/src/reducers/settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ const settings = handleActions(
},
[actions.toggleSettingStatus]: (state, { payload }) => {
const { settingsList } = state;
const { settingKey } = payload;
const { settingKey, value } = payload;

const setting = settingsList[settingKey];

const newSetting = {
const newSetting = value || {
...setting,
enabled: !setting.enabled,
};
Expand Down
1 change: 1 addition & 0 deletions internal/filtering/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,7 @@ func (d *DNSFilter) RegisterFilteringHandlers() {
registerHTTP(http.MethodPost, "/control/safesearch/enable", d.handleSafeSearchEnable)
registerHTTP(http.MethodPost, "/control/safesearch/disable", d.handleSafeSearchDisable)
registerHTTP(http.MethodGet, "/control/safesearch/status", d.handleSafeSearchStatus)
registerHTTP(http.MethodPut, "/control/safesearch/settings", d.handleSafeSearchSettings)

registerHTTP(http.MethodGet, "/control/rewrite/list", d.handleRewriteList)
registerHTTP(http.MethodPost, "/control/rewrite/add", d.handleRewriteAdd)
Expand Down
2 changes: 1 addition & 1 deletion internal/filtering/safesearch.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ type SafeSearch interface {
// SafeSearchConfig is a struct with safe search related settings.
type SafeSearchConfig struct {
// CustomResolver is the resolver used by safe search.
CustomResolver Resolver `yaml:"-"`
CustomResolver Resolver `yaml:"-" json:"-"`

// Enabled indicates if safe search is enabled entirely.
Enabled bool `yaml:"enabled" json:"enabled"`
Expand Down
Loading

0 comments on commit df61741

Please sign in to comment.