Pull request: all: imp uniq validation err msgs

Updates #3975.

Squashed commit of the following:

commit f8578c2afb1bb5786e7b855a1715e0757bc08510
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Tue Dec 28 16:39:13 2021 +0300

    aghalgo: imp docs

commit d9fc625f7c4ede2cf4b0683ad5efd0ddf9b966b1
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Tue Dec 28 16:21:24 2021 +0300

    all: imp uniq validation err msgs
This commit is contained in:
Ainar Garipov
2021-12-28 17:00:52 +03:00
parent 2ed1f939b5
commit d2ce06e1ca
10 changed files with 166 additions and 128 deletions

View File

@@ -7,8 +7,8 @@ import (
"net/http"
"strings"
"github.com/AdguardTeam/AdGuardHome/internal/aghalgo"
"github.com/AdguardTeam/AdGuardHome/internal/aghhttp"
"github.com/AdguardTeam/golibs/errors"
"github.com/AdguardTeam/golibs/log"
"github.com/AdguardTeam/golibs/netutil"
"github.com/AdguardTeam/golibs/stringutil"
@@ -194,62 +194,46 @@ func (s *Server) handleAccessList(w http.ResponseWriter, r *http.Request) {
}
}
func isUniq(slice []string) (ok bool, uniqueMap map[string]unit) {
exists := make(map[string]unit)
for _, key := range slice {
if _, has := exists[key]; has {
return false, nil
}
exists[key] = unit{}
}
return true, exists
}
func intersect(mapA, mapB map[string]unit) bool {
for key := range mapA {
if _, has := mapB[key]; has {
return true
}
}
return false
}
// validateAccessSet checks the internal accessListJSON lists. To search for
// duplicates, we cannot compare the new stringutil.Set and []string, because
// creating a set for a large array can be an unnecessary algorithmic complexity
func validateAccessSet(list accessListJSON) (err error) {
const (
errAllowedDup errors.Error = "duplicates in allowed clients"
errDisallowedDup errors.Error = "duplicates in disallowed clients"
errBlockedDup errors.Error = "duplicates in blocked hosts"
errIntersect errors.Error = "some items in allowed and " +
"disallowed lists at the same time"
)
ok, allowedClients := isUniq(list.AllowedClients)
if !ok {
return errAllowedDup
func validateAccessSet(list *accessListJSON) (err error) {
allowed, err := validateStrUniq(list.AllowedClients)
if err != nil {
return fmt.Errorf("validating allowed clients: %w", err)
}
ok, disallowedClients := isUniq(list.DisallowedClients)
if !ok {
return errDisallowedDup
disallowed, err := validateStrUniq(list.DisallowedClients)
if err != nil {
return fmt.Errorf("validating disallowed clients: %w", err)
}
ok, _ = isUniq(list.BlockedHosts)
if !ok {
return errBlockedDup
_, err = validateStrUniq(list.BlockedHosts)
if err != nil {
return fmt.Errorf("validating blocked hosts: %w", err)
}
if intersect(allowedClients, disallowedClients) {
return errIntersect
merged := allowed.Merge(disallowed)
err = merged.Validate(aghalgo.StringIsBefore)
if err != nil {
return fmt.Errorf("items in allowed and disallowed clients intersect: %w", err)
}
return nil
}
// validateStrUniq returns an informative error if clients are not unique.
func validateStrUniq(clients []string) (uv aghalgo.UniquenessValidator, err error) {
uv = make(aghalgo.UniquenessValidator, len(clients))
for _, c := range clients {
uv.Add(c)
}
return uv, uv.Validate(aghalgo.StringIsBefore)
}
func (s *Server) handleAccessSet(w http.ResponseWriter, r *http.Request) {
list := accessListJSON{}
list := &accessListJSON{}
err := json.NewDecoder(r.Body).Decode(&list)
if err != nil {
aghhttp.Error(r, w, http.StatusBadRequest, "decoding request: %s", err)