Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 121 additions & 0 deletions internal/configmgr/clients.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
package configmgr

import (
"github.com/AdguardTeam/AdGuardHome/internal/client"
"github.com/AdguardTeam/golibs/errors"
"github.com/AdguardTeam/golibs/validate"
"github.com/c2h5oh/datasize"
)

// ClientsConfig is the on-disk persistent client configuration.
type ClientsConfig struct {
// Sources defines the set of sources to fetch the runtime clients from.
Sources *ClientSourcesConfig `yaml:"runtime_sources"`

// Persistent are the configured clients.
Persistent []*Client `yaml:"persistent"`
}

// ClientSourcesConfig is used to configure where the runtime clients will be
// obtained from.
type ClientSourcesConfig struct {
// ARP enables the ARP source of runtime clients.
ARP bool `yaml:"arp"`

// DHCP enables the DHCP source of runtime clients.
DHCP bool `yaml:"dhcp"`

// HostsFile enables the system hosts file source of runtime clients.
HostsFile bool `yaml:"hosts"`

// RDNS enables the reverse DNS source of runtime clients.
RDNS bool `yaml:"rdns"`

// WHOIS enables the WHOIS source of runtime clients.
WHOIS bool `yaml:"whois"`
}

// Client represents the on-disk persistent client.
type Client struct {
// BlockedServices is the configuration of blocked services of a client.
BlockedServices *BlockedServices `yaml:"blocked_services"`

// SafeSearchConf is the safe search configuration of a client.
SafeSearchConf *SafeSearch `yaml:"safe_search"`

// Name is the human-readable name of the client.
Name string `yaml:"name"`

// IDs are the identifiers of the client, such as IP addresses, CIDRs, MAC
// addresses, or ClientIDs.
IDs []string `yaml:"ids"`

// Tags are the tags of the client.
Tags []string `yaml:"tags"`

// Upstreams are the custom upstream DNS servers of the client.
Upstreams []string `yaml:"upstreams"`

// UID is the unique identifier of the persistent client.
UID client.UID `yaml:"uid"`

// UpstreamsCacheSize is the DNS cache size.
UpstreamsCacheSize datasize.ByteSize `yaml:"upstreams_cache_size"`

// FilteringEnabled indicates if filtering is enabled for the client.
FilteringEnabled bool `yaml:"filtering_enabled"`

// IgnoreQueryLog indicates if the client's queries are excluded from the
// query log.
IgnoreQueryLog bool `yaml:"ignore_querylog"`

// IgnoreStatistics indicates if the client's queries are excluded from the
// statistics.
IgnoreStatistics bool `yaml:"ignore_statistics"`

// ParentalEnabled indicates if parental control is enabled for the client.
ParentalEnabled bool `yaml:"parental_enabled"`

// SafeBrowsingEnabled indicates if safe browsing is enabled for the client.
SafeBrowsingEnabled bool `yaml:"safebrowsing_enabled"`

// UpstreamsCacheEnabled indicates if the DNS cache is enabled.
UpstreamsCacheEnabled bool `yaml:"upstreams_cache_enabled"`

// UseGlobalBlockedServices indicates if the client uses the global blocked
// services configuration.
UseGlobalBlockedServices bool `yaml:"use_global_blocked_services"`

// UseGlobalSettings indicates if the client uses the global filtering
// settings.
UseGlobalSettings bool `yaml:"use_global_settings"`
}

// type check
var _ validate.Interface = (*ClientsConfig)(nil)

// Validate implements the [validate.Interface] interface for *ClientsConfig.
func (c *ClientsConfig) Validate() (err error) {
if c == nil {
return errors.ErrNoValue
}

return errors.Join(
validate.NotNil("runtime_sources", c.Sources),
validate.Slice("persistent", c.Persistent),
)
}

// type check
var _ validate.Interface = (*Client)(nil)

// Validate implements the [validate.Interface] interface for *Client.
func (c *Client) Validate() (err error) {
if c == nil {
return errors.ErrNoValue
}

// TODO(d.kolyshev): Add more validations.

return nil
}
41 changes: 38 additions & 3 deletions internal/configmgr/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,17 @@ import (
// TODO(d.kolyshev): Use.
// TODO(d.kolyshev): Add tests and contracts.
type Config struct {
// Clients is a block with persistent clients configuration settings.
Clients *ClientsConfig `yaml:"clients"`

// DHCP is a block with DHCP configuration params.
DHCP *DHCPConfig `yaml:"dhcp"`

// DNSConfig is a block with DNS configuration params.
DNSConfig *DNSConfig `yaml:"dns"`
// DNS is a block with DNS configuration params.
DNS *DNSConfig `yaml:"dns"`

// Filtering is a block with DNS filtering configuration settings.
Filtering *FilteringConfig `yaml:"filtering"`

// HTTP is a block with web API configuration settings.
HTTP *HTTPConfig `yaml:"http"`
Expand All @@ -28,13 +34,18 @@ type Config struct {
// QueryLog is a block with query log configuration settings.
QueryLog *QueryLogConfig `yaml:"querylog"`

// OS is a block with OS-related configuration settings.
OS *OSConfig `yaml:"os"`

// Stats is a block with statistics configuration settings.
Stats *StatsConfig `yaml:"statistics"`

// TLS is a block with TLS configuration settings.
TLS *TLSConfig `yaml:"tls"`

// ProxyURL is the address of proxy server for the internal HTTP client.
//
// TODO(d.kolyshev): Use [url.URL].
ProxyURL string `yaml:"http_proxy"`

// Language is a two-letter ISO 639-1 language code.
Expand All @@ -45,9 +56,22 @@ type Config struct {
// Theme is a web UI theme for current user.
Theme string `yaml:"theme"`

// Filters is a slice of the blocking filter lists.
//
// TODO(e.burkov): Move all the filtering configuration fields into the
// only configuration subsection covering the changes with a single
// migration. Also keep the blocked services in mind.
Filters []*Filter `yaml:"filters"`

// UserRules is a list of custom rules.
UserRules []string `yaml:"user_rules"`

// Users are the clients capable for accessing the web interface.
Users []*WebUser `yaml:"users"`

// WhitelistFilters is a slice of the allowing filter lists.
WhitelistFilters []*Filter `yaml:"whitelist_filters"`

// AuthAttempts is the maximum number of failed login attempts a user can do
// before being blocked.
AuthAttempts uint `yaml:"auth_attempts"`
Expand Down Expand Up @@ -78,17 +102,26 @@ func (c *Config) Validate() (err error) {

// Keep this in the same order as the fields in the config.
validators := container.KeyValues[string, validate.Interface]{{
Key: "clients",
Value: c.Clients,
}, {
Key: "dhcp",
Value: c.DHCP,
}, {
Key: "dns",
Value: c.DNSConfig,
Value: c.DNS,
}, {
Key: "filtering",
Value: c.Filtering,
}, {
Key: "http",
Value: c.HTTP,
}, {
Key: "log",
Value: c.Log,
}, {
Key: "os",
Value: c.OS,
}, {
Key: "querylog",
Value: c.QueryLog,
Expand All @@ -112,7 +145,9 @@ func (c *Config) Validate() (err error) {
}
}

errs = validate.AppendSlice(errs, "filters", c.Filters)
errs = validate.AppendSlice(errs, "users", c.Users)
errs = validate.AppendSlice(errs, "whitelist_filters", c.WhitelistFilters)

return errors.Join(errs...)
}
38 changes: 38 additions & 0 deletions internal/configmgr/filter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package configmgr

import (
"github.com/AdguardTeam/golibs/errors"
"github.com/AdguardTeam/golibs/netutil/urlutil"
"github.com/AdguardTeam/golibs/validate"
"github.com/AdguardTeam/urlfilter/rules"
)

// Filter represents the on-disk filter list.
type Filter struct {
// URL is the location of the filter list, which can be a URL or an absolute
// file path.
URL *urlutil.URL `yaml:"url"`

// Name is the human-readable name of the filter list.
Name string `yaml:"name"`

// ID is automatically assigned when filter is added.
ID rules.ListID `yaml:"id"`

// Enabled indicates whether the filter list is used.
Enabled bool `yaml:"enabled"`
}

// type check
var _ validate.Interface = (*Filter)(nil)

// Validate implements the [validate.Interface] interface for *Filter.
func (f *Filter) Validate() (err error) {
if f == nil {
return errors.ErrNoValue
}

// TODO(d.kolyshev): Add more validations.

return nil
}
Loading
Loading