Pull request 2286: AGDNS-2374-slog-safesearch
Squashed commit of the following:
commit 1909dfed99b8815c1215c709efcae77a70b52ea3
Merge: 3856fda5f 2c64ab5a5
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date: Wed Oct 9 16:21:38 2024 +0300
Merge branch 'master' into AGDNS-2374-slog-safesearch
commit 3856fda5f38a89d2df86bd8701e79d7f3fc02bb7
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date: Tue Oct 8 20:04:34 2024 +0300
home: imp code
commit de774009aa82bf45022fd9c359296e7ab45bf93d
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date: Mon Oct 7 16:41:58 2024 +0300
all: imp code
commit 038bae59d51497de1db7153e00e779db30f79721
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date: Thu Oct 3 20:24:48 2024 +0300
all: imp code
commit 792975e248bb04bce5a8ec767441fcf253c6d00f
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date: Thu Oct 3 15:46:40 2024 +0300
all: slog safesearch
This commit is contained in:
@@ -3,6 +3,7 @@ package home
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"net/netip"
|
||||
"slices"
|
||||
"sync"
|
||||
@@ -13,17 +14,23 @@ import (
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/client"
|
||||
"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/schedule"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/whois"
|
||||
"github.com/AdguardTeam/dnsproxy/proxy"
|
||||
"github.com/AdguardTeam/dnsproxy/upstream"
|
||||
"github.com/AdguardTeam/golibs/errors"
|
||||
"github.com/AdguardTeam/golibs/logutil/slogutil"
|
||||
"github.com/AdguardTeam/golibs/stringutil"
|
||||
)
|
||||
|
||||
// clientsContainer is the storage of all runtime and persistent clients.
|
||||
type clientsContainer struct {
|
||||
// baseLogger is used to create loggers with custom prefixes for safe search
|
||||
// filter. It must not be nil.
|
||||
baseLogger *slog.Logger
|
||||
|
||||
// storage stores information about persistent clients.
|
||||
storage *client.Storage
|
||||
|
||||
@@ -61,6 +68,8 @@ type BlockedClientChecker interface {
|
||||
// dhcpServer: optional
|
||||
// Note: this function must be called only once
|
||||
func (clients *clientsContainer) Init(
|
||||
ctx context.Context,
|
||||
baseLogger *slog.Logger,
|
||||
objects []*clientObject,
|
||||
dhcpServer client.DHCP,
|
||||
etcHosts *aghnet.HostsContainer,
|
||||
@@ -72,13 +81,14 @@ func (clients *clientsContainer) Init(
|
||||
return errors.Error("clients container already initialized")
|
||||
}
|
||||
|
||||
clients.baseLogger = baseLogger
|
||||
clients.safeSearchCacheSize = filteringConf.SafeSearchCacheSize
|
||||
clients.safeSearchCacheTTL = time.Minute * time.Duration(filteringConf.CacheTime)
|
||||
|
||||
confClients := make([]*client.Persistent, 0, len(objects))
|
||||
for i, o := range objects {
|
||||
var p *client.Persistent
|
||||
p, err = o.toPersistent(clients.safeSearchCacheSize, clients.safeSearchCacheTTL)
|
||||
p, err = o.toPersistent(ctx, baseLogger, clients.safeSearchCacheSize, clients.safeSearchCacheTTL)
|
||||
if err != nil {
|
||||
return fmt.Errorf("init persistent client at index %d: %w", i, err)
|
||||
}
|
||||
@@ -168,6 +178,8 @@ type clientObject struct {
|
||||
|
||||
// toPersistent returns an initialized persistent client if there are no errors.
|
||||
func (o *clientObject) toPersistent(
|
||||
ctx context.Context,
|
||||
baseLogger *slog.Logger,
|
||||
safeSearchCacheSize uint,
|
||||
safeSearchCacheTTL time.Duration,
|
||||
) (cli *client.Persistent, err error) {
|
||||
@@ -203,14 +215,23 @@ func (o *clientObject) toPersistent(
|
||||
}
|
||||
|
||||
if o.SafeSearchConf.Enabled {
|
||||
err = cli.SetSafeSearch(
|
||||
o.SafeSearchConf,
|
||||
safeSearchCacheSize,
|
||||
safeSearchCacheTTL,
|
||||
logger := baseLogger.With(
|
||||
slogutil.KeyPrefix, safesearch.LogPrefix,
|
||||
safesearch.LogKeyClient, cli.Name,
|
||||
)
|
||||
var ss *safesearch.Default
|
||||
ss, err = safesearch.NewDefault(ctx, &safesearch.DefaultConfig{
|
||||
Logger: logger,
|
||||
ServicesConfig: o.SafeSearchConf,
|
||||
ClientName: cli.Name,
|
||||
CacheSize: safeSearchCacheSize,
|
||||
CacheTTL: safeSearchCacheTTL,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("init safesearch %q: %w", cli.Name, err)
|
||||
}
|
||||
|
||||
cli.SafeSearch = ss
|
||||
}
|
||||
|
||||
if o.BlockedServices == nil {
|
||||
|
||||
@@ -7,6 +7,8 @@ import (
|
||||
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/client"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/filtering"
|
||||
"github.com/AdguardTeam/golibs/logutil/slogutil"
|
||||
"github.com/AdguardTeam/golibs/testutil"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
@@ -20,7 +22,18 @@ func newClientsContainer(t *testing.T) (c *clientsContainer) {
|
||||
testing: true,
|
||||
}
|
||||
|
||||
require.NoError(t, c.Init(nil, client.EmptyDHCP{}, nil, nil, &filtering.Config{}))
|
||||
ctx := testutil.ContextWithTimeout(t, testTimeout)
|
||||
err := c.Init(
|
||||
ctx,
|
||||
slogutil.NewDiscardLogger(),
|
||||
nil,
|
||||
client.EmptyDHCP{},
|
||||
nil,
|
||||
nil,
|
||||
&filtering.Config{},
|
||||
)
|
||||
|
||||
require.NoError(t, err)
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package home
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
@@ -10,8 +11,10 @@ import (
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/aghhttp"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/client"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/filtering"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/filtering/safesearch"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/schedule"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/whois"
|
||||
"github.com/AdguardTeam/golibs/logutil/slogutil"
|
||||
)
|
||||
|
||||
// clientJSON is a common structure used by several handlers to deal with
|
||||
@@ -181,6 +184,7 @@ func initPrev(cj clientJSON, prev *client.Persistent) (c *client.Persistent, err
|
||||
// jsonToClient converts JSON object to persistent client object if there are no
|
||||
// errors.
|
||||
func (clients *clientsContainer) jsonToClient(
|
||||
ctx context.Context,
|
||||
cj clientJSON,
|
||||
prev *client.Persistent,
|
||||
) (c *client.Persistent, err error) {
|
||||
@@ -207,14 +211,23 @@ func (clients *clientsContainer) jsonToClient(
|
||||
c.UseOwnBlockedServices = !cj.UseGlobalBlockedServices
|
||||
|
||||
if c.SafeSearchConf.Enabled {
|
||||
err = c.SetSafeSearch(
|
||||
c.SafeSearchConf,
|
||||
clients.safeSearchCacheSize,
|
||||
clients.safeSearchCacheTTL,
|
||||
logger := clients.baseLogger.With(
|
||||
slogutil.KeyPrefix, safesearch.LogPrefix,
|
||||
safesearch.LogKeyClient, c.Name,
|
||||
)
|
||||
var ss *safesearch.Default
|
||||
ss, err = safesearch.NewDefault(ctx, &safesearch.DefaultConfig{
|
||||
Logger: logger,
|
||||
ServicesConfig: c.SafeSearchConf,
|
||||
ClientName: c.Name,
|
||||
CacheSize: clients.safeSearchCacheSize,
|
||||
CacheTTL: clients.safeSearchCacheTTL,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("creating safesearch for client %q: %w", c.Name, err)
|
||||
}
|
||||
|
||||
c.SafeSearch = ss
|
||||
}
|
||||
|
||||
return c, nil
|
||||
@@ -321,7 +334,7 @@ func (clients *clientsContainer) handleAddClient(w http.ResponseWriter, r *http.
|
||||
return
|
||||
}
|
||||
|
||||
c, err := clients.jsonToClient(cj, nil)
|
||||
c, err := clients.jsonToClient(r.Context(), cj, nil)
|
||||
if err != nil {
|
||||
aghhttp.Error(r, w, http.StatusBadRequest, "%s", err)
|
||||
|
||||
@@ -391,7 +404,7 @@ func (clients *clientsContainer) handleUpdateClient(w http.ResponseWriter, r *ht
|
||||
return
|
||||
}
|
||||
|
||||
c, err := clients.jsonToClient(dj.Data, nil)
|
||||
c, err := clients.jsonToClient(r.Context(), dj.Data, nil)
|
||||
if err != nil {
|
||||
aghhttp.Error(r, w, http.StatusBadRequest, "%s", err)
|
||||
|
||||
|
||||
@@ -11,14 +11,19 @@ import (
|
||||
"net/url"
|
||||
"slices"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/client"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/filtering"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/schedule"
|
||||
"github.com/AdguardTeam/golibs/testutil"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// testTimeout is the common timeout for tests and contexts.
|
||||
const testTimeout = 1 * time.Second
|
||||
|
||||
const (
|
||||
testClientIP1 = "1.1.1.1"
|
||||
testClientIP2 = "2.2.2.2"
|
||||
@@ -103,9 +108,10 @@ func assertPersistentClients(tb testing.TB, clients *clientsContainer, want []*c
|
||||
require.NoError(tb, err)
|
||||
|
||||
var got []*client.Persistent
|
||||
ctx := testutil.ContextWithTimeout(tb, testTimeout)
|
||||
for _, cj := range clientList.Clients {
|
||||
var c *client.Persistent
|
||||
c, err = clients.jsonToClient(*cj, nil)
|
||||
c, err = clients.jsonToClient(ctx, *cj, nil)
|
||||
require.NoError(tb, err)
|
||||
|
||||
got = append(got, c)
|
||||
@@ -125,10 +131,11 @@ func assertPersistentClientsData(
|
||||
tb.Helper()
|
||||
|
||||
var got []*client.Persistent
|
||||
ctx := testutil.ContextWithTimeout(tb, testTimeout)
|
||||
for _, cm := range data {
|
||||
for _, cj := range cm {
|
||||
var c *client.Persistent
|
||||
c, err := clients.jsonToClient(*cj, nil)
|
||||
c, err := clients.jsonToClient(ctx, *cj, nil)
|
||||
require.NoError(tb, err)
|
||||
|
||||
got = append(got, c)
|
||||
|
||||
@@ -278,8 +278,8 @@ func setupOpts(opts options) (err error) {
|
||||
}
|
||||
|
||||
// initContextClients initializes Context clients and related fields.
|
||||
func initContextClients(logger *slog.Logger) (err error) {
|
||||
err = setupDNSFilteringConf(config.Filtering)
|
||||
func initContextClients(ctx context.Context, logger *slog.Logger) (err error) {
|
||||
err = setupDNSFilteringConf(ctx, logger, config.Filtering)
|
||||
if err != nil {
|
||||
// Don't wrap the error, because it's informative enough as is.
|
||||
return err
|
||||
@@ -306,6 +306,8 @@ func initContextClients(logger *slog.Logger) (err error) {
|
||||
}
|
||||
|
||||
return Context.clients.Init(
|
||||
ctx,
|
||||
logger,
|
||||
config.Clients.Persistent,
|
||||
Context.dhcpServer,
|
||||
Context.etcHosts,
|
||||
@@ -355,7 +357,11 @@ func setupBindOpts(opts options) (err error) {
|
||||
}
|
||||
|
||||
// setupDNSFilteringConf sets up DNS filtering configuration settings.
|
||||
func setupDNSFilteringConf(conf *filtering.Config) (err error) {
|
||||
func setupDNSFilteringConf(
|
||||
ctx context.Context,
|
||||
baseLogger *slog.Logger,
|
||||
conf *filtering.Config,
|
||||
) (err error) {
|
||||
const (
|
||||
dnsTimeout = 3 * time.Second
|
||||
|
||||
@@ -446,12 +452,13 @@ func setupDNSFilteringConf(conf *filtering.Config) (err error) {
|
||||
conf.ParentalBlockHost = host
|
||||
}
|
||||
|
||||
conf.SafeSearch, err = safesearch.NewDefault(
|
||||
conf.SafeSearchConf,
|
||||
"default",
|
||||
conf.SafeSearchCacheSize,
|
||||
cacheTime,
|
||||
)
|
||||
logger := baseLogger.With(slogutil.KeyPrefix, safesearch.LogPrefix)
|
||||
conf.SafeSearch, err = safesearch.NewDefault(ctx, &safesearch.DefaultConfig{
|
||||
Logger: logger,
|
||||
ServicesConfig: conf.SafeSearchConf,
|
||||
CacheSize: conf.SafeSearchCacheSize,
|
||||
CacheTTL: cacheTime,
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("initializing safesearch: %w", err)
|
||||
}
|
||||
@@ -584,7 +591,10 @@ func run(opts options, clientBuildFS fs.FS, done chan struct{}) {
|
||||
// data first, but also to avoid relying on automatic Go init() function.
|
||||
filtering.InitModule()
|
||||
|
||||
err = initContextClients(slogLogger)
|
||||
// TODO(s.chzhen): Use it for the entire initialization process.
|
||||
ctx := context.Background()
|
||||
|
||||
err = initContextClients(ctx, slogLogger)
|
||||
fatalOnError(err)
|
||||
|
||||
err = setupOpts(opts)
|
||||
|
||||
Reference in New Issue
Block a user