Pull request: 1163 safesearch vol.2
Merge in DNS/adguard-home from 1163-safesearch-1-2-1 to master Squashed commit of the following: commit d3a5ebef35210019842145074e898129b42f1f2c Merge: b85264aec6706445Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Wed Mar 15 09:17:53 2023 +0700 Merge remote-tracking branch 'origin/master' into 1163-safesearch-1-2-1 # Conflicts: # CHANGELOG.md commit b85264aefc5f191ac6cb194b519f03ba15829a4e Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Tue Mar 14 00:16:07 2023 +0700 home: imp code commit ac2ed7a5ce8db40628e7d4d1c8634641e5f38b0b Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Mon Mar 13 23:02:06 2023 +0700 all: changelog commit f0fccafcb01f50c7051df53bbe9b02cab75aa71e Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Mon Mar 13 22:42:36 2023 +0700 all: changelog commit 37df29bf6372939644fb28e3d70365496e0cb4f6 Merge: b227b277595484e0Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Mon Mar 13 22:38:57 2023 +0700 Merge remote-tracking branch 'origin/master' into 1163-safesearch-1-2-1 commit b227b2775b4866d69241ad87acf99700715552cb Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Mon Mar 13 16:56:01 2023 +0700 all: imp docs commit 6fd39fc3565c3f4bc7a7113d17733c20dfe24d8d Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Mon Mar 13 16:55:03 2023 +0700 home: imp code commit 3bb3bb7c7dcf97b2a5602a7d2b6770c08b4d863d Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Mon Mar 13 12:16:53 2023 +0700 home: imp docs commit 5f573a56a9fd9942ad677fa0fae6b24228dab653 Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Mon Mar 13 11:56:47 2023 +0700 home: imp code commit 23eeb5552cf2510596b2311cc3eda53ac678ffcc Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Fri Mar 10 10:57:33 2023 +0700 home: imp code commit 643de2fca1b5917c61fe83e1e472222404f3cd21 Merge: dada6e63a2053526Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Thu Mar 9 21:03:08 2023 +0700 Merge remote-tracking branch 'origin/master' into 1163-safesearch-1-2-1 commit dada6e63ca5324d30775e2da1727da891743f654 Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Thu Mar 9 17:09:03 2023 +0700 all: imp docs commit 81a180d99dd9a995440d5f4e2ebca34678e7d0c7 Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Thu Mar 9 15:12:43 2023 +0700 all: imp code commit fa84877bc777004d246d71d0a9ae0bd9ee568a91 Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Thu Mar 9 10:53:05 2023 +0700 all: imp code commit 6d7e02e745d72921a693d4f09eec7ce21c2aefd4 Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Thu Mar 9 10:40:02 2023 +0700 all: imp docs commit 0a4332997070fb8d2fb3a34d32b92f57a325ff06 Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Tue Mar 7 22:00:52 2023 +0700 safesearch: fix merge commit 145c2222ba4cf7f8909b816d83829d2217c94243 Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Thu Mar 2 11:41:48 2023 +0700 safesearch: fix merge commit 14c6a8005fe15b5d5a39f91b17c96d8670975811 Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Wed Mar 1 12:50:09 2023 +0700 all: docs commit 2a85c8831866bf1c34c423a289461fc1e32667b5 Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Wed Mar 1 12:47:00 2023 +0700 all: use safesearch package
This commit is contained in:
@@ -4,6 +4,7 @@ import (
|
||||
"encoding"
|
||||
"fmt"
|
||||
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/filtering"
|
||||
"github.com/AdguardTeam/dnsproxy/proxy"
|
||||
)
|
||||
|
||||
@@ -15,6 +16,9 @@ type Client struct {
|
||||
// these upstream must be used.
|
||||
upstreamConfig *proxy.UpstreamConfig
|
||||
|
||||
safeSearchConf filtering.SafeSearchConfig
|
||||
SafeSearch filtering.SafeSearch
|
||||
|
||||
Name string
|
||||
|
||||
IDs []string
|
||||
@@ -24,7 +28,6 @@ type Client struct {
|
||||
|
||||
UseOwnSettings bool
|
||||
FilteringEnabled bool
|
||||
SafeSearchEnabled bool
|
||||
SafeBrowsingEnabled bool
|
||||
ParentalEnabled bool
|
||||
UseOwnBlockedServices bool
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/dhcpd"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/dnsforward"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/filtering"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/filtering/safesearch"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/querylog"
|
||||
"github.com/AdguardTeam/dnsproxy/proxy"
|
||||
"github.com/AdguardTeam/dnsproxy/upstream"
|
||||
@@ -69,6 +70,7 @@ func (clients *clientsContainer) Init(
|
||||
dhcpServer dhcpd.Interface,
|
||||
etcHosts *aghnet.HostsContainer,
|
||||
arpdb aghnet.ARPDB,
|
||||
filteringConf *filtering.Config,
|
||||
) {
|
||||
if clients.list != nil {
|
||||
log.Fatal("clients.list != nil")
|
||||
@@ -82,7 +84,7 @@ func (clients *clientsContainer) Init(
|
||||
clients.dhcpServer = dhcpServer
|
||||
clients.etcHosts = etcHosts
|
||||
clients.arpdb = arpdb
|
||||
clients.addFromConfig(objects)
|
||||
clients.addFromConfig(objects, filteringConf)
|
||||
|
||||
if clients.testing {
|
||||
return
|
||||
@@ -133,6 +135,8 @@ func (clients *clientsContainer) reloadARP() {
|
||||
|
||||
// clientObject is the YAML representation of a persistent client.
|
||||
type clientObject struct {
|
||||
SafeSearchConf filtering.SafeSearchConfig `yaml:"safe_search"`
|
||||
|
||||
Name string `yaml:"name"`
|
||||
|
||||
Tags []string `yaml:"tags"`
|
||||
@@ -143,14 +147,13 @@ type clientObject struct {
|
||||
UseGlobalSettings bool `yaml:"use_global_settings"`
|
||||
FilteringEnabled bool `yaml:"filtering_enabled"`
|
||||
ParentalEnabled bool `yaml:"parental_enabled"`
|
||||
SafeSearchEnabled bool `yaml:"safesearch_enabled"`
|
||||
SafeBrowsingEnabled bool `yaml:"safebrowsing_enabled"`
|
||||
UseGlobalBlockedServices bool `yaml:"use_global_blocked_services"`
|
||||
}
|
||||
|
||||
// addFromConfig initializes the clients container with objects from the
|
||||
// configuration file.
|
||||
func (clients *clientsContainer) addFromConfig(objects []*clientObject) {
|
||||
func (clients *clientsContainer) addFromConfig(objects []*clientObject, filteringConf *filtering.Config) {
|
||||
for _, o := range objects {
|
||||
cli := &Client{
|
||||
Name: o.Name,
|
||||
@@ -161,11 +164,28 @@ func (clients *clientsContainer) addFromConfig(objects []*clientObject) {
|
||||
UseOwnSettings: !o.UseGlobalSettings,
|
||||
FilteringEnabled: o.FilteringEnabled,
|
||||
ParentalEnabled: o.ParentalEnabled,
|
||||
SafeSearchEnabled: o.SafeSearchEnabled,
|
||||
safeSearchConf: o.SafeSearchConf,
|
||||
SafeBrowsingEnabled: o.SafeBrowsingEnabled,
|
||||
UseOwnBlockedServices: !o.UseGlobalBlockedServices,
|
||||
}
|
||||
|
||||
if o.SafeSearchConf.Enabled {
|
||||
o.SafeSearchConf.CustomResolver = safeSearchResolver{}
|
||||
|
||||
ss, err := safesearch.NewDefaultSafeSearch(
|
||||
o.SafeSearchConf,
|
||||
filteringConf.SafeSearchCacheSize,
|
||||
time.Minute*time.Duration(filteringConf.CacheTime),
|
||||
)
|
||||
if err != nil {
|
||||
log.Error("clients: init client safesearch %s: %s", cli.Name, err)
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
cli.SafeSearch = ss
|
||||
}
|
||||
|
||||
for _, s := range o.BlockedServices {
|
||||
if filtering.BlockedSvcKnown(s) {
|
||||
cli.BlockedServices = append(cli.BlockedServices, s)
|
||||
@@ -210,7 +230,7 @@ func (clients *clientsContainer) forConfig() (objs []*clientObject) {
|
||||
UseGlobalSettings: !cli.UseOwnSettings,
|
||||
FilteringEnabled: cli.FilteringEnabled,
|
||||
ParentalEnabled: cli.ParentalEnabled,
|
||||
SafeSearchEnabled: cli.SafeSearchEnabled,
|
||||
SafeSearchConf: cli.safeSearchConf,
|
||||
SafeBrowsingEnabled: cli.SafeBrowsingEnabled,
|
||||
UseGlobalBlockedServices: !cli.UseOwnBlockedServices,
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ func TestClients(t *testing.T) {
|
||||
clients := clientsContainer{}
|
||||
clients.testing = true
|
||||
|
||||
clients.Init(nil, nil, nil, nil)
|
||||
clients.Init(nil, nil, nil, nil, nil)
|
||||
|
||||
t.Run("add_success", func(t *testing.T) {
|
||||
var (
|
||||
@@ -201,7 +201,7 @@ func TestClientsWHOIS(t *testing.T) {
|
||||
clients := clientsContainer{
|
||||
testing: true,
|
||||
}
|
||||
clients.Init(nil, nil, nil, nil)
|
||||
clients.Init(nil, nil, nil, nil, nil)
|
||||
whois := &RuntimeClientWHOISInfo{
|
||||
Country: "AU",
|
||||
Orgname: "Example Org",
|
||||
@@ -250,7 +250,7 @@ func TestClientsAddExisting(t *testing.T) {
|
||||
clients := clientsContainer{
|
||||
testing: true,
|
||||
}
|
||||
clients.Init(nil, nil, nil, nil)
|
||||
clients.Init(nil, nil, nil, nil, nil)
|
||||
|
||||
t.Run("simple", func(t *testing.T) {
|
||||
ip := netip.MustParseAddr("1.1.1.1")
|
||||
@@ -328,7 +328,7 @@ func TestClientsCustomUpstream(t *testing.T) {
|
||||
clients := clientsContainer{
|
||||
testing: true,
|
||||
}
|
||||
clients.Init(nil, nil, nil, nil)
|
||||
clients.Init(nil, nil, nil, nil, nil)
|
||||
|
||||
// Add client with upstreams.
|
||||
ok, err := clients.Add(&Client{
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"net/netip"
|
||||
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/aghhttp"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/filtering"
|
||||
)
|
||||
|
||||
// clientJSON is a common structure used by several handlers to deal with
|
||||
@@ -35,9 +36,10 @@ type clientJSON struct {
|
||||
Tags []string `json:"tags"`
|
||||
Upstreams []string `json:"upstreams"`
|
||||
|
||||
FilteringEnabled bool `json:"filtering_enabled"`
|
||||
ParentalEnabled bool `json:"parental_enabled"`
|
||||
SafeBrowsingEnabled bool `json:"safebrowsing_enabled"`
|
||||
FilteringEnabled bool `json:"filtering_enabled"`
|
||||
ParentalEnabled bool `json:"parental_enabled"`
|
||||
SafeBrowsingEnabled bool `json:"safebrowsing_enabled"`
|
||||
// Deprecated: use safeSearchConf.
|
||||
SafeSearchEnabled bool `json:"safesearch_enabled"`
|
||||
UseGlobalBlockedServices bool `json:"use_global_blocked_services"`
|
||||
UseGlobalSettings bool `json:"use_global_settings"`
|
||||
@@ -88,6 +90,20 @@ func (clients *clientsContainer) handleGetClients(w http.ResponseWriter, r *http
|
||||
|
||||
// Convert JSON object to Client object
|
||||
func jsonToClient(cj clientJSON) (c *Client) {
|
||||
// TODO(d.kolyshev): Remove after cleaning the deprecated
|
||||
// [clientJSON.SafeSearchEnabled] field.
|
||||
safeSearchConf := filtering.SafeSearchConfig{Enabled: 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
|
||||
}
|
||||
|
||||
return &Client{
|
||||
Name: cj.Name,
|
||||
IDs: cj.IDs,
|
||||
@@ -95,7 +111,7 @@ func jsonToClient(cj clientJSON) (c *Client) {
|
||||
UseOwnSettings: !cj.UseGlobalSettings,
|
||||
FilteringEnabled: cj.FilteringEnabled,
|
||||
ParentalEnabled: cj.ParentalEnabled,
|
||||
SafeSearchEnabled: cj.SafeSearchEnabled,
|
||||
safeSearchConf: safeSearchConf,
|
||||
SafeBrowsingEnabled: cj.SafeBrowsingEnabled,
|
||||
|
||||
UseOwnBlockedServices: !cj.UseGlobalBlockedServices,
|
||||
@@ -107,6 +123,11 @@ func jsonToClient(cj clientJSON) (c *Client) {
|
||||
|
||||
// Convert Client object to JSON
|
||||
func clientToJSON(c *Client) (cj *clientJSON) {
|
||||
// TODO(d.kolyshev): Remove after cleaning the deprecated
|
||||
// [clientJSON.SafeSearchEnabled] field.
|
||||
cloneVal := c.safeSearchConf
|
||||
safeSearchConf := &cloneVal
|
||||
|
||||
return &clientJSON{
|
||||
Name: c.Name,
|
||||
IDs: c.IDs,
|
||||
@@ -114,7 +135,7 @@ func clientToJSON(c *Client) (cj *clientJSON) {
|
||||
UseGlobalSettings: !c.UseOwnSettings,
|
||||
FilteringEnabled: c.FilteringEnabled,
|
||||
ParentalEnabled: c.ParentalEnabled,
|
||||
SafeSearchEnabled: c.SafeSearchEnabled,
|
||||
SafeSearchEnabled: safeSearchConf.Enabled,
|
||||
SafeBrowsingEnabled: c.SafeBrowsingEnabled,
|
||||
|
||||
UseGlobalBlockedServices: !c.UseOwnBlockedServices,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package home
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/netip"
|
||||
@@ -426,7 +427,8 @@ func applyAdditionalFiltering(clientIP net.IP, clientID string, setts *filtering
|
||||
}
|
||||
|
||||
setts.FilteringEnabled = c.FilteringEnabled
|
||||
setts.SafeSearchEnabled = c.SafeSearchEnabled
|
||||
setts.SafeSearchEnabled = c.safeSearchConf.Enabled
|
||||
setts.ClientSafeSearch = c.SafeSearch
|
||||
setts.SafeBrowsingEnabled = c.SafeBrowsingEnabled
|
||||
setts.ParentalEnabled = c.ParentalEnabled
|
||||
}
|
||||
@@ -556,3 +558,29 @@ func nonDupEmptyHostNames(list []string) (set *stringutil.Set, err error) {
|
||||
|
||||
return set, nil
|
||||
}
|
||||
|
||||
// safeSearchResolver is a [filtering.Resolver] implementation used for safe
|
||||
// search.
|
||||
type safeSearchResolver struct{}
|
||||
|
||||
// type check
|
||||
var _ filtering.Resolver = safeSearchResolver{}
|
||||
|
||||
// LookupIP implements [filtering.Resolver] interface for safeSearchResolver.
|
||||
// It returns the slice of net.IP with IPv4 and IPv6 instances.
|
||||
func (r safeSearchResolver) LookupIP(_ context.Context, _, host string) (ips []net.IP, err error) {
|
||||
addrs, err := Context.dnsServer.Resolve(host)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(addrs) == 0 {
|
||||
return nil, fmt.Errorf("couldn't lookup host: %s", host)
|
||||
}
|
||||
|
||||
for _, a := range addrs {
|
||||
ips = append(ips, a.IP)
|
||||
}
|
||||
|
||||
return ips, nil
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ import (
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/dhcpd"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/dnsforward"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/filtering"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/filtering/safesearch"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/querylog"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/stats"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/updater"
|
||||
@@ -298,6 +299,16 @@ func setupConfig(opts options) (err error) {
|
||||
config.DNS.DnsfilterConf.UserRules = slices.Clone(config.UserRules)
|
||||
config.DNS.DnsfilterConf.HTTPClient = Context.client
|
||||
|
||||
config.DNS.DnsfilterConf.SafeSearchConf.CustomResolver = safeSearchResolver{}
|
||||
config.DNS.DnsfilterConf.SafeSearch, err = safesearch.NewDefaultSafeSearch(
|
||||
config.DNS.DnsfilterConf.SafeSearchConf,
|
||||
config.DNS.DnsfilterConf.SafeSearchCacheSize,
|
||||
time.Minute*time.Duration(config.DNS.DnsfilterConf.CacheTime),
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("initializing safesearch: %w", err)
|
||||
}
|
||||
|
||||
config.DHCP.WorkDir = Context.workDir
|
||||
config.DHCP.HTTPRegister = httpRegister
|
||||
config.DHCP.ConfigModified = onConfigModified
|
||||
@@ -328,33 +339,16 @@ func setupConfig(opts options) (err error) {
|
||||
arpdb = aghnet.NewARPDB()
|
||||
}
|
||||
|
||||
Context.clients.Init(config.Clients.Persistent, Context.dhcpServer, Context.etcHosts, arpdb)
|
||||
Context.clients.Init(config.Clients.Persistent, Context.dhcpServer, Context.etcHosts, arpdb, config.DNS.DnsfilterConf)
|
||||
|
||||
if opts.bindPort != 0 {
|
||||
tcpPorts := aghalg.UniqChecker[tcpPort]{}
|
||||
addPorts(tcpPorts, tcpPort(opts.bindPort))
|
||||
|
||||
udpPorts := aghalg.UniqChecker[udpPort]{}
|
||||
addPorts(udpPorts, udpPort(config.DNS.Port))
|
||||
|
||||
if config.TLS.Enabled {
|
||||
addPorts(
|
||||
tcpPorts,
|
||||
tcpPort(config.TLS.PortHTTPS),
|
||||
tcpPort(config.TLS.PortDNSOverTLS),
|
||||
tcpPort(config.TLS.PortDNSCrypt),
|
||||
)
|
||||
|
||||
addPorts(udpPorts, udpPort(config.TLS.PortDNSOverQUIC))
|
||||
}
|
||||
|
||||
if err = tcpPorts.Validate(); err != nil {
|
||||
return fmt.Errorf("validating tcp ports: %w", err)
|
||||
} else if err = udpPorts.Validate(); err != nil {
|
||||
return fmt.Errorf("validating udp ports: %w", err)
|
||||
}
|
||||
|
||||
config.BindPort = opts.bindPort
|
||||
|
||||
err = checkPorts()
|
||||
if err != nil {
|
||||
// Don't wrap the error, because it's informative enough as is.
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// override bind host/port from the console
|
||||
@@ -368,6 +362,34 @@ func setupConfig(opts options) (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// checkPorts is a helper for ports validation in config.
|
||||
func checkPorts() (err error) {
|
||||
tcpPorts := aghalg.UniqChecker[tcpPort]{}
|
||||
addPorts(tcpPorts, tcpPort(config.BindPort))
|
||||
|
||||
udpPorts := aghalg.UniqChecker[udpPort]{}
|
||||
addPorts(udpPorts, udpPort(config.DNS.Port))
|
||||
|
||||
if config.TLS.Enabled {
|
||||
addPorts(
|
||||
tcpPorts,
|
||||
tcpPort(config.TLS.PortHTTPS),
|
||||
tcpPort(config.TLS.PortDNSOverTLS),
|
||||
tcpPort(config.TLS.PortDNSCrypt),
|
||||
)
|
||||
|
||||
addPorts(udpPorts, udpPort(config.TLS.PortDNSOverQUIC))
|
||||
}
|
||||
|
||||
if err = tcpPorts.Validate(); err != nil {
|
||||
return fmt.Errorf("validating tcp ports: %w", err)
|
||||
} else if err = udpPorts.Validate(); err != nil {
|
||||
return fmt.Errorf("validating udp ports: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func initWeb(opts options, clientBuildFS fs.FS) (web *Web, err error) {
|
||||
var clientFS fs.FS
|
||||
if opts.localFrontend {
|
||||
|
||||
@@ -22,7 +22,7 @@ import (
|
||||
)
|
||||
|
||||
// currentSchemaVersion is the current schema version.
|
||||
const currentSchemaVersion = 17
|
||||
const currentSchemaVersion = 19
|
||||
|
||||
// These aliases are provided for convenience.
|
||||
type (
|
||||
@@ -90,6 +90,8 @@ func upgradeConfigSchema(oldVersion int, diskConf yobj) (err error) {
|
||||
upgradeSchema14to15,
|
||||
upgradeSchema15to16,
|
||||
upgradeSchema16to17,
|
||||
upgradeSchema17to18,
|
||||
upgradeSchema18to19,
|
||||
}
|
||||
|
||||
n := 0
|
||||
@@ -943,6 +945,125 @@ func upgradeSchema16to17(diskConf yobj) (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// upgradeSchema17to18 performs the following changes:
|
||||
//
|
||||
// # BEFORE:
|
||||
// 'dns':
|
||||
// 'safesearch_enabled': true
|
||||
//
|
||||
// # AFTER:
|
||||
// 'dns':
|
||||
// 'safe_search':
|
||||
// 'enabled': true
|
||||
// 'bing': true
|
||||
// 'duckduckgo': true
|
||||
// 'google': true
|
||||
// 'pixabay': true
|
||||
// 'yandex': true
|
||||
// 'youtube': true
|
||||
func upgradeSchema17to18(diskConf yobj) (err error) {
|
||||
log.Printf("Upgrade yaml: 17 to 18")
|
||||
diskConf["schema_version"] = 18
|
||||
|
||||
dnsVal, ok := diskConf["dns"]
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
dns, ok := dnsVal.(yobj)
|
||||
if !ok {
|
||||
return fmt.Errorf("unexpected type of dns: %T", dnsVal)
|
||||
}
|
||||
|
||||
safeSearch := yobj{
|
||||
"enabled": true,
|
||||
"bing": true,
|
||||
"duckduckgo": true,
|
||||
"google": true,
|
||||
"pixabay": true,
|
||||
"yandex": true,
|
||||
"youtube": true,
|
||||
}
|
||||
|
||||
const safeSearchKey = "safesearch_enabled"
|
||||
|
||||
v, has := dns[safeSearchKey]
|
||||
if has {
|
||||
safeSearch["enabled"] = v
|
||||
}
|
||||
delete(dns, safeSearchKey)
|
||||
|
||||
dns["safe_search"] = safeSearch
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// upgradeSchema18to19 performs the following changes:
|
||||
//
|
||||
// # BEFORE:
|
||||
// 'clients':
|
||||
// 'persistent':
|
||||
// - 'name': 'client-name'
|
||||
// 'safesearch_enabled': true
|
||||
//
|
||||
// # AFTER:
|
||||
// 'clients':
|
||||
// 'persistent':
|
||||
// - 'name': 'client-name'
|
||||
// 'safe_search':
|
||||
// 'enabled': true
|
||||
// 'bing': true
|
||||
// 'duckduckgo': true
|
||||
// 'google': true
|
||||
// 'pixabay': true
|
||||
// 'yandex': true
|
||||
// 'youtube': true
|
||||
func upgradeSchema18to19(diskConf yobj) (err error) {
|
||||
log.Printf("Upgrade yaml: 18 to 19")
|
||||
diskConf["schema_version"] = 19
|
||||
|
||||
clientsVal, ok := diskConf["clients"]
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
clients, ok := clientsVal.(yobj)
|
||||
if !ok {
|
||||
return fmt.Errorf("unexpected type of clients: %T", clientsVal)
|
||||
}
|
||||
|
||||
persistent, ok := clients["persistent"].([]yobj)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
const safeSearchKey = "safesearch_enabled"
|
||||
|
||||
for i := range persistent {
|
||||
c := persistent[i]
|
||||
|
||||
safeSearch := yobj{
|
||||
"enabled": true,
|
||||
"bing": true,
|
||||
"duckduckgo": true,
|
||||
"google": true,
|
||||
"pixabay": true,
|
||||
"yandex": true,
|
||||
"youtube": true,
|
||||
}
|
||||
|
||||
v, has := c[safeSearchKey]
|
||||
if has {
|
||||
safeSearch["enabled"] = v
|
||||
}
|
||||
delete(c, safeSearchKey)
|
||||
|
||||
c["safe_search"] = safeSearch
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// TODO(a.garipov): Replace with log.Output when we port it to our logging
|
||||
// package.
|
||||
func funcName() string {
|
||||
|
||||
@@ -808,3 +808,146 @@ func TestUpgradeSchema16to17(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpgradeSchema17to18(t *testing.T) {
|
||||
const newSchemaVer = 18
|
||||
|
||||
defaultWantObj := yobj{
|
||||
"dns": yobj{
|
||||
"safe_search": yobj{
|
||||
"enabled": true,
|
||||
"bing": true,
|
||||
"duckduckgo": true,
|
||||
"google": true,
|
||||
"pixabay": true,
|
||||
"yandex": true,
|
||||
"youtube": true,
|
||||
},
|
||||
},
|
||||
"schema_version": newSchemaVer,
|
||||
}
|
||||
|
||||
testCases := []struct {
|
||||
in yobj
|
||||
want yobj
|
||||
name string
|
||||
}{{
|
||||
in: yobj{"dns": yobj{}},
|
||||
want: defaultWantObj,
|
||||
name: "default_values",
|
||||
}, {
|
||||
in: yobj{"dns": yobj{"safesearch_enabled": true}},
|
||||
want: defaultWantObj,
|
||||
name: "enabled",
|
||||
}, {
|
||||
in: yobj{"dns": yobj{"safesearch_enabled": false}},
|
||||
want: yobj{
|
||||
"dns": yobj{
|
||||
"safe_search": map[string]any{
|
||||
"enabled": false,
|
||||
"bing": true,
|
||||
"duckduckgo": true,
|
||||
"google": true,
|
||||
"pixabay": true,
|
||||
"yandex": true,
|
||||
"youtube": true,
|
||||
},
|
||||
},
|
||||
"schema_version": newSchemaVer,
|
||||
},
|
||||
name: "disabled",
|
||||
}}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
err := upgradeSchema17to18(tc.in)
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, tc.want, tc.in)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpgradeSchema18to19(t *testing.T) {
|
||||
const newSchemaVer = 19
|
||||
|
||||
defaultWantObj := yobj{
|
||||
"clients": yobj{
|
||||
"persistent": []yobj{{
|
||||
"name": "localhost",
|
||||
"safe_search": yobj{
|
||||
"enabled": true,
|
||||
"bing": true,
|
||||
"duckduckgo": true,
|
||||
"google": true,
|
||||
"pixabay": true,
|
||||
"yandex": true,
|
||||
"youtube": true,
|
||||
},
|
||||
}},
|
||||
},
|
||||
"schema_version": newSchemaVer,
|
||||
}
|
||||
|
||||
testCases := []struct {
|
||||
in yobj
|
||||
want yobj
|
||||
name string
|
||||
}{{
|
||||
in: yobj{
|
||||
"clients": yobj{},
|
||||
},
|
||||
want: yobj{
|
||||
"clients": yobj{},
|
||||
"schema_version": newSchemaVer,
|
||||
},
|
||||
name: "no_clients",
|
||||
}, {
|
||||
in: yobj{
|
||||
"clients": yobj{
|
||||
"persistent": []yobj{{"name": "localhost"}},
|
||||
},
|
||||
},
|
||||
want: defaultWantObj,
|
||||
name: "default_values",
|
||||
}, {
|
||||
in: yobj{
|
||||
"clients": yobj{
|
||||
"persistent": []yobj{{"name": "localhost", "safesearch_enabled": true}},
|
||||
},
|
||||
},
|
||||
want: defaultWantObj,
|
||||
name: "enabled",
|
||||
}, {
|
||||
in: yobj{
|
||||
"clients": yobj{
|
||||
"persistent": []yobj{{"name": "localhost", "safesearch_enabled": false}},
|
||||
},
|
||||
},
|
||||
want: yobj{
|
||||
"clients": yobj{"persistent": []yobj{{
|
||||
"name": "localhost",
|
||||
"safe_search": yobj{
|
||||
"enabled": false,
|
||||
"bing": true,
|
||||
"duckduckgo": true,
|
||||
"google": true,
|
||||
"pixabay": true,
|
||||
"yandex": true,
|
||||
"youtube": true,
|
||||
},
|
||||
}}},
|
||||
"schema_version": newSchemaVer,
|
||||
},
|
||||
name: "disabled",
|
||||
}}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
err := upgradeSchema18to19(tc.in)
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, tc.want, tc.in)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user