Skip to content

Commit

Permalink
all: add blocked services schedule
Browse files Browse the repository at this point in the history
  • Loading branch information
schzhn committed Jun 20, 2023
1 parent 2902f03 commit c5b614d
Show file tree
Hide file tree
Showing 8 changed files with 203 additions and 29 deletions.
8 changes: 8 additions & 0 deletions internal/filtering/blocked.go
Expand Up @@ -55,6 +55,14 @@ type BlockedServices struct {
IDs []string `yaml:"ids"`
}

// Clone returns a deep copy of blocked services.
func (s *BlockedServices) Clone() (c *BlockedServices) {
return &BlockedServices{
Schedule: s.Schedule.Clone(),
IDs: append([]string{}, s.IDs...),
}
}

// BlockedSvcKnown returns true if a blocked service ID is known.
func BlockedSvcKnown(s string) (ok bool) {
_, ok = serviceRules[s]
Expand Down
15 changes: 10 additions & 5 deletions internal/home/client.go
Expand Up @@ -22,12 +22,14 @@ type Client struct {
safeSearchConf filtering.SafeSearchConfig
SafeSearch filtering.SafeSearch

// BlockedServices is the configuration of blocked services of a client.
BlockedServices *filtering.BlockedServices

Name string

IDs []string
Tags []string
BlockedServices []string
Upstreams []string
IDs []string
Tags []string
Upstreams []string

UseOwnSettings bool
FilteringEnabled bool
Expand All @@ -43,9 +45,12 @@ type Client struct {
func (c *Client) ShallowClone() (sh *Client) {
clone := *c

if c.BlockedServices != nil {
clone.BlockedServices = c.BlockedServices.Clone()
}

clone.IDs = stringutil.CloneSlice(c.IDs)
clone.Tags = stringutil.CloneSlice(c.Tags)
clone.BlockedServices = stringutil.CloneSlice(c.BlockedServices)
clone.Upstreams = stringutil.CloneSlice(c.Upstreams)

return &clone
Expand Down
27 changes: 12 additions & 15 deletions internal/home/clients.go
Expand Up @@ -147,12 +147,14 @@ func (clients *clientsContainer) reloadARP() {
type clientObject struct {
SafeSearchConf filtering.SafeSearchConfig `yaml:"safe_search"`

// BlockedServices is the configuration of blocked services of a client.
BlockedServices *filtering.BlockedServices `yaml:"blocked_services"`

Name string `yaml:"name"`

Tags []string `yaml:"tags"`
IDs []string `yaml:"ids"`
BlockedServices []string `yaml:"blocked_services"`
Upstreams []string `yaml:"upstreams"`
IDs []string `yaml:"ids"`
Tags []string `yaml:"tags"`
Upstreams []string `yaml:"upstreams"`

UseGlobalSettings bool `yaml:"use_global_settings"`
FilteringEnabled bool `yaml:"filtering_enabled"`
Expand Down Expand Up @@ -199,13 +201,7 @@ func (clients *clientsContainer) addFromConfig(objects []*clientObject, filterin
}
}

for _, s := range o.BlockedServices {
if filtering.BlockedSvcKnown(s) {
cli.BlockedServices = append(cli.BlockedServices, s)
} else {
log.Info("clients: skipping unknown blocked service %q", s)
}
}
cli.BlockedServices = o.BlockedServices.Clone()

for _, t := range o.Tags {
if clients.allTags.Has(t) {
Expand Down Expand Up @@ -235,10 +231,11 @@ func (clients *clientsContainer) forConfig() (objs []*clientObject) {
o := &clientObject{
Name: cli.Name,

Tags: stringutil.CloneSlice(cli.Tags),
IDs: stringutil.CloneSlice(cli.IDs),
BlockedServices: stringutil.CloneSlice(cli.BlockedServices),
Upstreams: stringutil.CloneSlice(cli.Upstreams),
BlockedServices: cli.BlockedServices.Clone(),

IDs: stringutil.CloneSlice(cli.IDs),
Tags: stringutil.CloneSlice(cli.Tags),
Upstreams: stringutil.CloneSlice(cli.Upstreams),

UseGlobalSettings: !cli.UseOwnSettings,
FilteringEnabled: cli.FilteringEnabled,
Expand Down
15 changes: 10 additions & 5 deletions internal/home/clientshttp.go
Expand Up @@ -121,10 +121,14 @@ func (clients *clientsContainer) jsonToClient(cj clientJSON, prev *Client) (c *C

Name: cj.Name,

IDs: cj.IDs,
Tags: cj.Tags,
BlockedServices: cj.BlockedServices,
Upstreams: cj.Upstreams,
BlockedServices: &filtering.BlockedServices{
Schedule: prev.BlockedServices.Schedule.Clone(),
IDs: cj.BlockedServices,
},

IDs: cj.IDs,
Tags: cj.Tags,
Upstreams: cj.Upstreams,

UseOwnSettings: !cj.UseGlobalSettings,
FilteringEnabled: cj.FilteringEnabled,
Expand Down Expand Up @@ -178,7 +182,8 @@ func clientToJSON(c *Client) (cj *clientJSON) {
SafeBrowsingEnabled: c.SafeBrowsingEnabled,

UseGlobalBlockedServices: !c.UseOwnBlockedServices,
BlockedServices: c.BlockedServices,

BlockedServices: c.BlockedServices.IDs,

Upstreams: c.Upstreams,

Expand Down
10 changes: 7 additions & 3 deletions internal/home/dns.go
Expand Up @@ -8,6 +8,7 @@ import (
"net/url"
"os"
"path/filepath"
"time"

"github.com/AdguardTeam/AdGuardHome/internal/aghalg"
"github.com/AdguardTeam/AdGuardHome/internal/aghhttp"
Expand Down Expand Up @@ -414,12 +415,15 @@ func applyAdditionalFiltering(clientIP net.IP, clientID string, setts *filtering

if c.UseOwnBlockedServices {
// TODO(e.burkov): Get rid of this crutch.
svcs := c.BlockedServices
svcs := c.BlockedServices.IDs
if svcs == nil {
svcs = []string{}
}
Context.filters.ApplyBlockedServicesList(setts, svcs)
log.Debug("%s: services for client %q set: %s", pref, c.Name, svcs)

if !c.BlockedServices.Schedule.Contains(time.Now()) {
Context.filters.ApplyBlockedServicesList(setts, svcs)
log.Debug("%s: services for client %q set: %s", pref, c.Name, svcs)
}
}

setts.ClientName = c.Name
Expand Down
72 changes: 71 additions & 1 deletion internal/home/upgrade.go
Expand Up @@ -22,7 +22,7 @@ import (
)

// currentSchemaVersion is the current schema version.
const currentSchemaVersion = 21
const currentSchemaVersion = 22

// These aliases are provided for convenience.
type (
Expand Down Expand Up @@ -95,6 +95,7 @@ func upgradeConfigSchema(oldVersion int, diskConf yobj) (err error) {
upgradeSchema18to19,
upgradeSchema19to20,
upgradeSchema20to21,
upgradeSchema21to22,
}

n := 0
Expand Down Expand Up @@ -1179,6 +1180,75 @@ func upgradeSchema20to21(diskConf yobj) (err error) {
return nil
}

// upgradeSchema21to22 performs the following changes:
//
// # BEFORE:
// 'persistent':
// - 'name': 'client_name'
// 'blocked_services':
// - 'svc_name'
//
// # AFTER:
// 'persistent':
// - 'name': 'client_name'
// 'blocked_services':
// 'ids':
// - 'svc_name'
// 'schedule':
// 'time_zone': 'Local'
func upgradeSchema21to22(diskConf yobj) (err error) {
log.Printf("Upgrade yaml: 21 to 22")
diskConf["schema_version"] = 22

const field = "blocked_services"

clientsVal, ok := diskConf["clients"]
if !ok {
return nil
}

clients, ok := clientsVal.(yobj)
if !ok {
return fmt.Errorf("unexpected type of clients: %T", clientsVal)
}

persistentVal, ok := clients["persistent"]
if !ok {
return nil
}

persistent, ok := persistentVal.([]any)
if !ok {
return fmt.Errorf("unexpected type of persistent clients: %T", persistentVal)
}

for _, val := range persistent {
c, k := val.(yobj)
if !k {
return fmt.Errorf("unexpected type of client: %T", val)
}

blockedVal, k := c[field]
if !k {
continue
}

services, k := blockedVal.(yarr)
if !k {
return fmt.Errorf("unexpected type of blocked: %T", blockedVal)
}

c[field] = yobj{
"ids": services,
"schedule": yobj{
"time_zone": "Local",
},
}
}

return nil
}

// TODO(a.garipov): Replace with log.Output when we port it to our logging
// package.
func funcName() string {
Expand Down
70 changes: 70 additions & 0 deletions internal/home/upgrade_test.go
Expand Up @@ -1183,3 +1183,73 @@ func TestUpgradeSchema20to21(t *testing.T) {
})
}
}

func TestUpgradeSchema21to22(t *testing.T) {
const newSchemaVer = 22

testCases := []struct {
in yobj
want yobj
name string
}{{
in: yobj{
"clients": yobj{},
},
want: yobj{
"clients": yobj{},
"schema_version": newSchemaVer,
},
name: "nothing",
}, {
in: yobj{
"clients": yobj{
"persistent": []any{yobj{"name": "localhost", "blocked_services": yarr{}}},
},
},
want: yobj{
"clients": yobj{
"persistent": []any{yobj{
"name": "localhost",
"blocked_services": yobj{
"ids": yarr{},
"schedule": yobj{
"time_zone": "Local",
},
},
}},
},
"schema_version": newSchemaVer,
},
name: "no_services",
}, {
in: yobj{
"clients": yobj{
"persistent": []any{yobj{"name": "localhost", "blocked_services": yarr{"ok"}}},
},
},
want: yobj{
"clients": yobj{
"persistent": []any{yobj{
"name": "localhost",
"blocked_services": yobj{
"ids": yarr{"ok"},
"schedule": yobj{
"time_zone": "Local",
},
},
}},
},
"schema_version": newSchemaVer,
},
name: "services",
}}

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
err := upgradeSchema21to22(tc.in)
require.NoError(t, err)

assert.Equal(t, tc.want, tc.in)
})
}
}
15 changes: 15 additions & 0 deletions internal/schedule/schedule.go
Expand Up @@ -6,6 +6,7 @@ import (
"time"

"github.com/AdguardTeam/golibs/errors"
"github.com/AdguardTeam/golibs/log"
"github.com/AdguardTeam/golibs/timeutil"
"gopkg.in/yaml.v3"
)
Expand All @@ -28,6 +29,20 @@ func EmptyWeekly() (w *Weekly) {
}
}

// Clone returns a deep copy of a weekly.
func (w *Weekly) Clone() (c *Weekly) {
tz := w.location.String()
loc, err := time.LoadLocation(tz)
if err != nil {
log.Debug("schedule: cloning location: %s", err)
}

return &Weekly{
location: loc,
days: w.days,
}
}

// Contains returns true if t is within the corresponding day range of the
// schedule in the schedule's time zone.
func (w *Weekly) Contains(t time.Time) (ok bool) {
Expand Down

0 comments on commit c5b614d

Please sign in to comment.