Pull request 2110: AG-27492-client-persistent

Squashed commit of the following:

commit 6605cd17a2e5137cf69c853c2a956b2443e81ce9
Merge: 5b294a268 bec3cab56
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Thu Dec 28 16:51:39 2023 +0300

    Merge branch 'master' into AG-27492-client-persistent

commit 5b294a26848e173b26eb9496b3c380b847a9fa1b
Merge: afe4d5f16 d75712bb9
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Wed Dec 27 19:13:50 2023 +0300

    Merge branch 'master' into AG-27492-client-persistent

commit afe4d5f1659c474173139ed4c841d72306ed27ac
Merge: 05dc0bfda ad147ac7b
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Tue Dec 26 14:59:10 2023 +0300

    Merge branch 'master' into AG-27492-client-persistent

commit 05dc0bfda2001cececc37c040f0cee632921aae4
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Wed Dec 20 19:44:04 2023 +0300

    home: imp err msg

commit c3b21c739ccb4436e9606579e3fb46cc32821a81
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Mon Dec 18 15:05:29 2023 +0300

    all: imp docs

commit a2118f5aedd93c16ffeb35d14dbcd2b3a1cdb4a4
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Fri Dec 15 18:27:50 2023 +0300

    all: add persistent client uid
This commit is contained in:
Stanislav Chzhen
2023-12-28 17:26:17 +03:00
parent bec3cab56c
commit 94d437d404
7 changed files with 243 additions and 156 deletions

View File

@@ -61,6 +61,7 @@ type clientJSON struct {
UpstreamsCacheEnabled aghalg.NullBool `json:"upstreams_cache_enabled"`
}
// runtimeClientJSON is a JSON representation of the [client.Runtime].
type runtimeClientJSON struct {
WHOIS *whois.Info `json:"whois_info"`
@@ -69,6 +70,8 @@ type runtimeClientJSON struct {
Source client.Source `json:"source"`
}
// clientListJSON contains lists of persistent clients, runtime clients and also
// supported tags.
type clientListJSON struct {
Clients []*clientJSON `json:"clients"`
RuntimeClients []runtimeClientJSON `json:"auto_clients"`
@@ -126,32 +129,36 @@ func (clients *clientsContainer) handleGetClients(w http.ResponseWriter, r *http
aghhttp.WriteJSONResponseOK(w, r, data)
}
// jsonToClient converts JSON object to Client object.
func (clients *clientsContainer) jsonToClient(cj clientJSON, prev *Client) (c *Client, err error) {
safeSearchConf := copySafeSearch(cj.SafeSearchConf, cj.SafeSearchEnabled)
// initPrev initializes the persistent client with the default or previous
// client properties.
func initPrev(cj clientJSON, prev *persistentClient) (c *persistentClient, err error) {
var (
uid UID
ignoreQueryLog bool
ignoreStatistics bool
upsCacheEnabled bool
upsCacheSize uint32
)
if prev != nil {
uid = prev.UID
ignoreQueryLog = prev.IgnoreQueryLog
ignoreStatistics = prev.IgnoreStatistics
upsCacheEnabled = prev.UpstreamsCacheEnabled
upsCacheSize = prev.UpstreamsCacheSize
}
var ignoreQueryLog bool
if cj.IgnoreQueryLog != aghalg.NBNull {
ignoreQueryLog = cj.IgnoreQueryLog == aghalg.NBTrue
} else if prev != nil {
ignoreQueryLog = prev.IgnoreQueryLog
}
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 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)
@@ -159,31 +166,49 @@ func (clients *clientsContainer) jsonToClient(cj clientJSON, prev *Client) (c *C
return nil, fmt.Errorf("invalid blocked services: %w", err)
}
c = &Client{
safeSearchConf: safeSearchConf,
if (uid == UID{}) {
uid, err = NewUID()
if err != nil {
return nil, fmt.Errorf("generating uid: %w", err)
}
}
Name: cj.Name,
BlockedServices: svcs,
IDs: cj.IDs,
Tags: cj.Tags,
Upstreams: cj.Upstreams,
UseOwnSettings: !cj.UseGlobalSettings,
FilteringEnabled: cj.FilteringEnabled,
ParentalEnabled: cj.ParentalEnabled,
SafeBrowsingEnabled: cj.SafeBrowsingEnabled,
UseOwnBlockedServices: !cj.UseGlobalBlockedServices,
return &persistentClient{
BlockedServices: svcs,
UID: uid,
IgnoreQueryLog: ignoreQueryLog,
IgnoreStatistics: ignoreStatistics,
UpstreamsCacheEnabled: upsCacheEnabled,
UpstreamsCacheSize: upsCacheSize,
}, nil
}
// jsonToClient converts JSON object to persistent client object if there are no
// errors.
func (clients *clientsContainer) jsonToClient(
cj clientJSON,
prev *persistentClient,
) (c *persistentClient, err error) {
c, err = initPrev(cj, prev)
if err != nil {
// Don't wrap the error since it's informative enough as is.
return nil, err
}
if safeSearchConf.Enabled {
c.safeSearchConf = copySafeSearch(cj.SafeSearchConf, cj.SafeSearchEnabled)
c.Name = cj.Name
c.IDs = cj.IDs
c.Tags = cj.Tags
c.Upstreams = cj.Upstreams
c.UseOwnSettings = !cj.UseGlobalSettings
c.FilteringEnabled = cj.FilteringEnabled
c.ParentalEnabled = cj.ParentalEnabled
c.SafeBrowsingEnabled = cj.SafeBrowsingEnabled
c.UseOwnBlockedServices = !cj.UseGlobalBlockedServices
if c.safeSearchConf.Enabled {
err = c.setSafeSearch(
safeSearchConf,
c.safeSearchConf,
clients.safeSearchCacheSize,
clients.safeSearchCacheTTL,
)
@@ -228,7 +253,7 @@ func copySafeSearch(
func copyBlockedServices(
sch *schedule.Weekly,
svcStrs []string,
prev *Client,
prev *persistentClient,
) (svcs *filtering.BlockedServices, err error) {
var weekly *schedule.Weekly
if sch != nil {
@@ -252,8 +277,8 @@ func copyBlockedServices(
return svcs, nil
}
// clientToJSON converts Client object to JSON.
func clientToJSON(c *Client) (cj *clientJSON) {
// clientToJSON converts persistent client object to JSON object.
func clientToJSON(c *persistentClient) (cj *clientJSON) {
// TODO(d.kolyshev): Remove after cleaning the deprecated
// [clientJSON.SafeSearchEnabled] field.
cloneVal := c.safeSearchConf
@@ -302,7 +327,7 @@ func (clients *clientsContainer) handleAddClient(w http.ResponseWriter, r *http.
return
}
ok, err := clients.Add(c)
ok, err := clients.add(c)
if err != nil {
aghhttp.Error(r, w, http.StatusBadRequest, "%s", err)
@@ -334,7 +359,7 @@ func (clients *clientsContainer) handleDelClient(w http.ResponseWriter, r *http.
return
}
if !clients.Del(cj.Name) {
if !clients.remove(cj.Name) {
aghhttp.Error(r, w, http.StatusBadRequest, "Client not found")
return
@@ -343,6 +368,7 @@ func (clients *clientsContainer) handleDelClient(w http.ResponseWriter, r *http.
onConfigModified()
}
// updateJSON contains the name and data of the updated persistent client.
type updateJSON struct {
Name string `json:"name"`
Data clientJSON `json:"data"`
@@ -366,7 +392,7 @@ func (clients *clientsContainer) handleUpdateClient(w http.ResponseWriter, r *ht
return
}
var prev *Client
var prev *persistentClient
var ok bool
func() {
@@ -389,7 +415,7 @@ func (clients *clientsContainer) handleUpdateClient(w http.ResponseWriter, r *ht
return
}
err = clients.Update(prev, c)
err = clients.update(prev, c)
if err != nil {
aghhttp.Error(r, w, http.StatusBadRequest, "%s", err)
@@ -410,7 +436,7 @@ func (clients *clientsContainer) handleFindClient(w http.ResponseWriter, r *http
}
ip, _ := netip.ParseAddr(idStr)
c, ok := clients.Find(idStr)
c, ok := clients.find(idStr)
var cj *clientJSON
if !ok {
cj = clients.findRuntime(ip, idStr)