Compare commits
12 Commits
ADG-9783
...
6263-custo
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f6b704fb58 | ||
|
|
780d001cef | ||
|
|
820bcf0e23 | ||
|
|
e7ca515630 | ||
|
|
23392d08b1 | ||
|
|
a09cd190c0 | ||
|
|
feb15745d2 | ||
|
|
789060e4d4 | ||
|
|
a700bfb42e | ||
|
|
7669419b59 | ||
|
|
4a9dc1d6c1 | ||
|
|
944e0d7a4b |
@@ -25,6 +25,7 @@ NOTE: Add new changes BELOW THIS COMMENT.
|
||||
|
||||
### Added
|
||||
|
||||
- Ability to set client's custom DNS cache ([#6362], [dnsproxy#169]).
|
||||
- Ability to disable plain-DNS serving through configuration file if an
|
||||
encrypted protocol is already used ([#1660]).
|
||||
- Ability to specify rate limiting settings in the Web UI ([#6369]).
|
||||
@@ -48,10 +49,13 @@ NOTE: Add new changes BELOW THIS COMMENT.
|
||||
|
||||
[#1660]: https://github.com/AdguardTeam/AdGuardHome/issues/1660
|
||||
[#5759]: https://github.com/AdguardTeam/AdGuardHome/issues/5759
|
||||
[#6362]: https://github.com/AdguardTeam/AdGuardHome/issues/6362
|
||||
[#6369]: https://github.com/AdguardTeam/AdGuardHome/issues/6369
|
||||
[#6402]: https://github.com/AdguardTeam/AdGuardHome/issues/6402
|
||||
[#6420]: https://github.com/AdguardTeam/AdGuardHome/issues/6420
|
||||
|
||||
[dnsproxy#169] https://github.com/AdguardTeam/dnsproxy/issues/169
|
||||
|
||||
<!--
|
||||
NOTE: Add new changes ABOVE THIS COMMENT.
|
||||
-->
|
||||
|
||||
@@ -734,5 +734,8 @@
|
||||
"wednesday_short": "Wed",
|
||||
"thursday_short": "Thu",
|
||||
"friday_short": "Fri",
|
||||
"saturday_short": "Sat"
|
||||
"saturday_short": "Sat",
|
||||
"upstream_dns_cache_configuration": "Upstream DNS cache configuration",
|
||||
"enable_upstream_dns_cache": "Enable DNS caching for this client's custom upstream configuration",
|
||||
"dns_cache_size": "DNS cache size, in bytes"
|
||||
}
|
||||
|
||||
@@ -79,6 +79,10 @@ const ClientsTable = ({
|
||||
} else {
|
||||
config.tags = [];
|
||||
}
|
||||
|
||||
if (typeof values.upstreams_cache_size === 'string') {
|
||||
config.upstreams_cache_size = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (modalType === MODAL_TYPE.EDIT_FILTERS) {
|
||||
|
||||
@@ -12,8 +12,13 @@ import i18n from '../../../i18n';
|
||||
import Tabs from '../../ui/Tabs';
|
||||
import Examples from '../Dns/Upstream/Examples';
|
||||
import { ScheduleForm } from '../../Filters/Services/ScheduleForm';
|
||||
import { toggleAllServices, trimLinesAndRemoveEmpty, captitalizeWords } from '../../../helpers/helpers';
|
||||
import {
|
||||
toggleAllServices,
|
||||
trimLinesAndRemoveEmpty,
|
||||
captitalizeWords,
|
||||
} from '../../../helpers/helpers';
|
||||
import {
|
||||
toNumber,
|
||||
renderInputField,
|
||||
renderGroupField,
|
||||
CheckboxField,
|
||||
@@ -21,7 +26,7 @@ import {
|
||||
renderTextareaField,
|
||||
} from '../../../helpers/form';
|
||||
import { validateClientId, validateRequiredValue } from '../../../helpers/validators';
|
||||
import { CLIENT_ID_LINK, FORM_NAME } from '../../../helpers/constants';
|
||||
import { CLIENT_ID_LINK, FORM_NAME, UINT32_RANGE } from '../../../helpers/constants';
|
||||
import './Service.css';
|
||||
|
||||
const settingsCheckboxes = [
|
||||
@@ -307,6 +312,35 @@ let Form = (props) => {
|
||||
normalizeOnBlur={trimLinesAndRemoveEmpty}
|
||||
/>
|
||||
<Examples />
|
||||
<div className="form__label--bold mt-5 mb-3">
|
||||
{t('upstream_dns_cache_configuration')}
|
||||
</div>
|
||||
<div className="form__group mb-2">
|
||||
<Field
|
||||
name="upstreams_cache_enabled"
|
||||
type="checkbox"
|
||||
component={CheckboxField}
|
||||
placeholder={t('enable_upstream_dns_cache')}
|
||||
/>
|
||||
</div>
|
||||
<div className="form__group form__group--settings">
|
||||
<label
|
||||
htmlFor="upstreams_cache_size"
|
||||
className="form__label"
|
||||
>
|
||||
{t('dns_cache_size')}
|
||||
</label>
|
||||
<Field
|
||||
name="upstreams_cache_size"
|
||||
type="number"
|
||||
component={renderInputField}
|
||||
placeholder={t('enter_cache_size')}
|
||||
className="form-control"
|
||||
normalize={toNumber}
|
||||
min={0}
|
||||
max={UINT32_RANGE.MAX}
|
||||
/>
|
||||
</div>
|
||||
</div>,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -20,6 +20,7 @@ type Client struct {
|
||||
// upstream must be used.
|
||||
upstreamConfig *proxy.CustomUpstreamConfig
|
||||
|
||||
// TODO(d.kolyshev): Make safeSearchConf a pointer.
|
||||
safeSearchConf filtering.SafeSearchConfig
|
||||
SafeSearch filtering.SafeSearch
|
||||
|
||||
|
||||
@@ -56,34 +56,9 @@ type clientJSON struct {
|
||||
|
||||
IgnoreQueryLog aghalg.NullBool `json:"ignore_querylog"`
|
||||
IgnoreStatistics aghalg.NullBool `json:"ignore_statistics"`
|
||||
}
|
||||
|
||||
// copySettings returns a copy of specific settings from JSON or a previous
|
||||
// client.
|
||||
func (j *clientJSON) copySettings(
|
||||
prev *Client,
|
||||
) (weekly *schedule.Weekly, ignoreQueryLog, ignoreStatistics bool) {
|
||||
if j.Schedule != nil {
|
||||
weekly = j.Schedule.Clone()
|
||||
} else if prev != nil && prev.BlockedServices != nil {
|
||||
weekly = prev.BlockedServices.Schedule.Clone()
|
||||
} else {
|
||||
weekly = schedule.EmptyWeekly()
|
||||
}
|
||||
|
||||
if j.IgnoreQueryLog != aghalg.NBNull {
|
||||
ignoreQueryLog = j.IgnoreQueryLog == aghalg.NBTrue
|
||||
} else if prev != nil {
|
||||
ignoreQueryLog = prev.IgnoreQueryLog
|
||||
}
|
||||
|
||||
if j.IgnoreStatistics != aghalg.NBNull {
|
||||
ignoreStatistics = j.IgnoreStatistics == aghalg.NBTrue
|
||||
} else if prev != nil {
|
||||
ignoreStatistics = prev.IgnoreStatistics
|
||||
}
|
||||
|
||||
return weekly, ignoreQueryLog, ignoreStatistics
|
||||
UpstreamsCacheSize uint32 `json:"upstreams_cache_size"`
|
||||
UpstreamsCacheEnabled aghalg.NullBool `json:"upstreams_cache_enabled"`
|
||||
}
|
||||
|
||||
type runtimeClientJSON struct {
|
||||
@@ -142,42 +117,35 @@ func (clients *clientsContainer) handleGetClients(w http.ResponseWriter, r *http
|
||||
|
||||
// jsonToClient converts JSON object to Client object.
|
||||
func (clients *clientsContainer) jsonToClient(cj clientJSON, prev *Client) (c *Client, err error) {
|
||||
var safeSearchConf filtering.SafeSearchConfig
|
||||
if cj.SafeSearchConf != nil {
|
||||
safeSearchConf = *cj.SafeSearchConf
|
||||
} else {
|
||||
// TODO(d.kolyshev): Remove after cleaning the deprecated
|
||||
// [clientJSON.SafeSearchEnabled] field.
|
||||
safeSearchConf = filtering.SafeSearchConfig{
|
||||
Enabled: cj.SafeSearchEnabled,
|
||||
}
|
||||
safeSearchConf := copySafeSearch(cj.SafeSearchConf, cj.SafeSearchEnabled)
|
||||
|
||||
// Set default service flags for enabled safesearch.
|
||||
if safeSearchConf.Enabled {
|
||||
safeSearchConf.Bing = true
|
||||
safeSearchConf.DuckDuckGo = true
|
||||
safeSearchConf.Google = true
|
||||
safeSearchConf.Pixabay = true
|
||||
safeSearchConf.Yandex = true
|
||||
safeSearchConf.YouTube = true
|
||||
}
|
||||
var ignoreQueryLog bool
|
||||
if cj.IgnoreQueryLog != aghalg.NBNull {
|
||||
ignoreQueryLog = cj.IgnoreQueryLog == aghalg.NBTrue
|
||||
} else if prev != nil {
|
||||
ignoreQueryLog = prev.IgnoreQueryLog
|
||||
}
|
||||
|
||||
weekly, ignoreQueryLog, ignoreStatistics := cj.copySettings(prev)
|
||||
|
||||
bs := &filtering.BlockedServices{
|
||||
Schedule: weekly,
|
||||
IDs: cj.BlockedServices,
|
||||
}
|
||||
err = bs.Validate()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("validating blocked services: %w", err)
|
||||
var ignoreStatistics bool
|
||||
if cj.IgnoreStatistics != aghalg.NBNull {
|
||||
ignoreStatistics = cj.IgnoreStatistics == aghalg.NBTrue
|
||||
} else if prev != nil {
|
||||
ignoreStatistics = prev.IgnoreStatistics
|
||||
}
|
||||
|
||||
var upsCacheEnabled bool
|
||||
var upsCacheSize uint32
|
||||
if prev != nil {
|
||||
upsCacheEnabled, upsCacheSize = prev.UpstreamsCacheEnabled, prev.UpstreamsCacheSize
|
||||
if cj.UpstreamsCacheEnabled != aghalg.NBNull {
|
||||
upsCacheEnabled = cj.UpstreamsCacheEnabled == aghalg.NBTrue
|
||||
upsCacheSize = cj.UpstreamsCacheSize
|
||||
} else if prev != nil {
|
||||
upsCacheEnabled = prev.UpstreamsCacheEnabled
|
||||
upsCacheSize = prev.UpstreamsCacheSize
|
||||
}
|
||||
|
||||
svcs, err := copyBlockedServices(cj.Schedule, cj.BlockedServices, prev)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid blocked services: %w", err)
|
||||
}
|
||||
|
||||
c = &Client{
|
||||
@@ -185,7 +153,7 @@ func (clients *clientsContainer) jsonToClient(cj clientJSON, prev *Client) (c *C
|
||||
|
||||
Name: cj.Name,
|
||||
|
||||
BlockedServices: bs,
|
||||
BlockedServices: svcs,
|
||||
|
||||
IDs: cj.IDs,
|
||||
Tags: cj.Tags,
|
||||
@@ -216,6 +184,63 @@ func (clients *clientsContainer) jsonToClient(cj clientJSON, prev *Client) (c *C
|
||||
return c, nil
|
||||
}
|
||||
|
||||
// copySafeSearch returns safe search config created from provided parameters.
|
||||
func copySafeSearch(
|
||||
jsonConf *filtering.SafeSearchConfig,
|
||||
enabled bool,
|
||||
) (conf filtering.SafeSearchConfig) {
|
||||
if jsonConf != nil {
|
||||
return *jsonConf
|
||||
}
|
||||
|
||||
// TODO(d.kolyshev): Remove after cleaning the deprecated
|
||||
// [clientJSON.SafeSearchEnabled] field.
|
||||
conf = filtering.SafeSearchConfig{
|
||||
Enabled: enabled,
|
||||
}
|
||||
|
||||
// Set default service flags for enabled safesearch.
|
||||
if conf.Enabled {
|
||||
conf.Bing = true
|
||||
conf.DuckDuckGo = true
|
||||
conf.Google = true
|
||||
conf.Pixabay = true
|
||||
conf.Yandex = true
|
||||
conf.YouTube = true
|
||||
}
|
||||
|
||||
return conf
|
||||
}
|
||||
|
||||
// copyBlockedServices converts a json blocked services to an internal blocked
|
||||
// services.
|
||||
func copyBlockedServices(
|
||||
sch *schedule.Weekly,
|
||||
svcStrs []string,
|
||||
prev *Client,
|
||||
) (svcs *filtering.BlockedServices, err error) {
|
||||
var weekly *schedule.Weekly
|
||||
if sch != nil {
|
||||
weekly = sch.Clone()
|
||||
} else if prev != nil && prev.BlockedServices != nil {
|
||||
weekly = prev.BlockedServices.Schedule.Clone()
|
||||
} else {
|
||||
weekly = schedule.EmptyWeekly()
|
||||
}
|
||||
|
||||
svcs = &filtering.BlockedServices{
|
||||
Schedule: weekly,
|
||||
IDs: svcStrs,
|
||||
}
|
||||
|
||||
err = svcs.Validate()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("validating blocked services: %w", err)
|
||||
}
|
||||
|
||||
return svcs, nil
|
||||
}
|
||||
|
||||
// clientToJSON converts Client object to JSON.
|
||||
func clientToJSON(c *Client) (cj *clientJSON) {
|
||||
// TODO(d.kolyshev): Remove after cleaning the deprecated
|
||||
@@ -243,6 +268,9 @@ func clientToJSON(c *Client) (cj *clientJSON) {
|
||||
|
||||
IgnoreQueryLog: aghalg.BoolToNullBool(c.IgnoreQueryLog),
|
||||
IgnoreStatistics: aghalg.BoolToNullBool(c.IgnoreStatistics),
|
||||
|
||||
UpstreamsCacheSize: c.UpstreamsCacheSize,
|
||||
UpstreamsCacheEnabled: aghalg.BoolToNullBool(c.UpstreamsCacheEnabled),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,18 @@
|
||||
|
||||
## v0.107.42: API changes
|
||||
|
||||
### The new fields `"upstreams_cache_enabled"` and `"upstreams_cache_size"` in `Client` object
|
||||
|
||||
* The new field `"upstreams_cache_enabled"` in `GET /control/clients`,
|
||||
`GET /control/clients/find`, `POST /control/clients/add`, and
|
||||
`POST /control/clients/update` methods shows if client's DNS cache is enabled
|
||||
for the client. If not set AdGuard Home will use default value (false).
|
||||
|
||||
* The new field `"upstreams_cache_size"` in `GET /control/clients`,
|
||||
`GET /control/clients/find`, `POST /control/clients/add`, and
|
||||
`POST /control/clients/update` methods is the size of client's DNS cache in
|
||||
bytes.
|
||||
|
||||
### The new field `"ratelimit_subnet_len_ipv4"` in `DNSConfig` object
|
||||
|
||||
* The new field `"ratelimit_subnet_len_ipv4"` in `GET /control/dns_info` and
|
||||
|
||||
@@ -2684,6 +2684,25 @@
|
||||
If `ignore_statistics` is not set in HTTP API `GET /clients/update`
|
||||
request then the existing value will not be changed.
|
||||
|
||||
This behaviour can be changed in the future versions.
|
||||
'type': 'boolean'
|
||||
'upstreams_cache_enabled':
|
||||
'description': |
|
||||
NOTE: If `upstreams_cache_enabled` is not set in HTTP API
|
||||
`GET /clients/add` request then default value (false) will be used.
|
||||
|
||||
If `upstreams_cache_enabled` is not set in HTTP API
|
||||
`GET /clients/update` request then the existing value will not be
|
||||
changed.
|
||||
|
||||
This behaviour can be changed in the future versions.
|
||||
'type': 'boolean'
|
||||
'upstreams_cache_size':
|
||||
'description': |
|
||||
NOTE: If `upstreams_cache_enabled` is not set in HTTP API
|
||||
`GET /clients/update` request then the existing value will not be
|
||||
changed.
|
||||
|
||||
This behaviour can be changed in the future versions.
|
||||
'type': 'boolean'
|
||||
'ClientAuto':
|
||||
|
||||
Reference in New Issue
Block a user