Pull request: home: imp client http api, docs

Updates #3075.

Squashed commit of the following:

commit c88fd2e24a19474bce736e5b6af7e094b43be390
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Thu May 6 16:09:49 2021 +0300

    home: imp code, docs

commit 8ae7d9001927d56394d2177c22fe114d98f01732
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Thu May 6 15:35:49 2021 +0300

    home: imp client http api, docs
This commit is contained in:
Ainar Garipov 2021-05-06 16:41:33 +03:00
parent f717776c64
commit 460aa1a5ba
4 changed files with 70 additions and 44 deletions

View File

@ -29,25 +29,25 @@ var webHandlersRegistered = false
// Client contains information about persistent clients. // Client contains information about persistent clients.
type Client struct { type Client struct {
// upstreamConfig is the custom upstream config for this client. If
// it's nil, it has not been initialized yet. If it's non-nil and
// empty, there are no valid upstreams. If it's non-nil and non-empty,
// these upstream must be used.
upstreamConfig *proxy.UpstreamConfig
Name string
IDs []string IDs []string
Tags []string Tags []string
Name string BlockedServices []string
UseOwnSettings bool // false: use global settings Upstreams []string
UseOwnSettings bool
FilteringEnabled bool FilteringEnabled bool
SafeSearchEnabled bool SafeSearchEnabled bool
SafeBrowsingEnabled bool SafeBrowsingEnabled bool
ParentalEnabled bool ParentalEnabled bool
UseOwnBlockedServices bool
UseOwnBlockedServices bool // false: use global settings
BlockedServices []string
Upstreams []string // list of upstream servers to be used for the client's requests
// Custom upstream config for this client
// nil: not yet initialized
// not nil, but empty: initialized, no good upstreams
// not nil, not empty: Upstreams ready to be used
upstreamConfig *proxy.UpstreamConfig
} }
type clientSource uint type clientSource uint
@ -63,9 +63,9 @@ const (
// RuntimeClient information // RuntimeClient information
type RuntimeClient struct { type RuntimeClient struct {
WhoisInfo *RuntimeClientWhoisInfo
Host string Host string
Source clientSource Source clientSource
WhoisInfo *RuntimeClientWhoisInfo
} }
// RuntimeClientWhoisInfo is the filtered WHOIS data for a runtime client. // RuntimeClientWhoisInfo is the filtered WHOIS data for a runtime client.

View File

@ -7,31 +7,38 @@ import (
"net/http" "net/http"
) )
// clientJSON is a common structure used by several handlers to deal with
// clients. Some of the fields are only necessary in one or two handlers and
// are thus made pointers with an omitempty tag.
//
// TODO(a.garipov): Consider using nullbool and an optional string here? Or
// split into several structs?
type clientJSON struct { type clientJSON struct {
// Disallowed, if non-nil and false, means that the client's IP is
// allowed. Otherwise, the IP is blocked.
Disallowed *bool `json:"disallowed,omitempty"`
// DisallowedRule is the rule due to which the client is disallowed.
// If Disallowed is true and this string is empty, the client IP is
// disallowed by the "allowed IP list", that is it is not included in
// the allowlist.
DisallowedRule *string `json:"disallowed_rule,omitempty"`
WhoisInfo *RuntimeClientWhoisInfo `json:"whois_info,omitempty"`
Name string `json:"name"`
BlockedServices []string `json:"blocked_services"`
IDs []string `json:"ids"` IDs []string `json:"ids"`
Tags []string `json:"tags"` Tags []string `json:"tags"`
Name string `json:"name"`
UseGlobalSettings bool `json:"use_global_settings"`
FilteringEnabled bool `json:"filtering_enabled"`
ParentalEnabled bool `json:"parental_enabled"`
SafeSearchEnabled bool `json:"safesearch_enabled"`
SafeBrowsingEnabled bool `json:"safebrowsing_enabled"`
UseGlobalBlockedServices bool `json:"use_global_blocked_services"`
BlockedServices []string `json:"blocked_services"`
Upstreams []string `json:"upstreams"` Upstreams []string `json:"upstreams"`
WhoisInfo *RuntimeClientWhoisInfo `json:"whois_info"` FilteringEnabled bool `json:"filtering_enabled"`
ParentalEnabled bool `json:"parental_enabled"`
// Disallowed - if true -- client's IP is not disallowed SafeBrowsingEnabled bool `json:"safebrowsing_enabled"`
// Otherwise, it is blocked. SafeSearchEnabled bool `json:"safesearch_enabled"`
Disallowed bool `json:"disallowed"` UseGlobalBlockedServices bool `json:"use_global_blocked_services"`
UseGlobalSettings bool `json:"use_global_settings"`
// DisallowedRule - the rule due to which the client is disallowed
// If Disallowed is true, and this string is empty - it means that the client IP
// is disallowed by the "allowed IP list", i.e. it is not included in allowed.
DisallowedRule string `json:"disallowed_rule"`
} }
type runtimeClientJSON struct { type runtimeClientJSON struct {
@ -126,8 +133,6 @@ func clientToJSON(c *Client) clientJSON {
BlockedServices: c.BlockedServices, BlockedServices: c.BlockedServices,
Upstreams: c.Upstreams, Upstreams: c.Upstreams,
WhoisInfo: &RuntimeClientWhoisInfo{},
} }
return cj return cj
@ -243,7 +248,8 @@ func (clients *clientsContainer) handleFindClient(w http.ResponseWriter, r *http
} }
} else { } else {
cj = clientToJSON(c) cj = clientToJSON(c)
cj.Disallowed, cj.DisallowedRule = clients.dnsServer.IsBlockedIP(ip) disallowed, rule := clients.dnsServer.IsBlockedIP(ip)
cj.Disallowed, cj.DisallowedRule = &disallowed, &rule
} }
data = append(data, map[string]clientJSON{ data = append(data, map[string]clientJSON{
@ -279,8 +285,8 @@ func (clients *clientsContainer) findRuntime(ip net.IP, idStr string) (cj client
cj = clientJSON{ cj = clientJSON{
IDs: []string{idStr}, IDs: []string{idStr},
Disallowed: disallowed, Disallowed: &disallowed,
DisallowedRule: rule, DisallowedRule: &rule,
WhoisInfo: &RuntimeClientWhoisInfo{}, WhoisInfo: &RuntimeClientWhoisInfo{},
} }
@ -288,7 +294,8 @@ func (clients *clientsContainer) findRuntime(ip net.IP, idStr string) (cj client
} }
cj = runtimeClientToJSON(idStr, rc) cj = runtimeClientToJSON(idStr, rc)
cj.Disallowed, cj.DisallowedRule = clients.dnsServer.IsBlockedIP(ip) disallowed, rule := clients.dnsServer.IsBlockedIP(ip)
cj.Disallowed, cj.DisallowedRule = &disallowed, &rule
return cj, true return cj, true
} }

View File

@ -4,6 +4,15 @@
## v0.106: API changes ## v0.106: API changes
### The field `"supported_tags"` in `GET /control/clients`
* Prefiously undocumented field `"supported_tags"` in the response is now
documented.
### The field `"whois_info"` in `GET /control/clients`
* Objects in the `"auto_clients"` array now have the `"whois_info"` field.
### New response code in `POST /control/login` ### New response code in `POST /control/login`
* `429` is returned when user is out of login attempts. It adds the * `429` is returned when user is out of login attempts. It adds the

View File

@ -2234,6 +2234,10 @@
'type': 'array' 'type': 'array'
'items': 'items':
'type': 'string' 'type': 'string'
'tags':
'items':
'type': 'string'
'type': 'array'
'ClientAuto': 'ClientAuto':
'type': 'object' 'type': 'object'
'description': 'Auto-Client information' 'description': 'Auto-Client information'
@ -2250,6 +2254,8 @@
'type': 'string' 'type': 'string'
'description': 'The source of this information' 'description': 'The source of this information'
'example': 'etc/hosts' 'example': 'etc/hosts'
'whois_info':
'$ref': '#/components/schemas/WhoisInfo'
'ClientUpdate': 'ClientUpdate':
'type': 'object' 'type': 'object'
'description': 'Client update request' 'description': 'Client update request'
@ -2384,6 +2390,10 @@
'$ref': '#/components/schemas/ClientsArray' '$ref': '#/components/schemas/ClientsArray'
'auto_clients': 'auto_clients':
'$ref': '#/components/schemas/ClientsAutoArray' '$ref': '#/components/schemas/ClientsAutoArray'
'supported_tags':
'items':
'type': 'string'
'type': 'array'
'ClientsArray': 'ClientsArray':
'type': 'array' 'type': 'array'
'items': 'items':