From 0500aa9591d1fb52f24182734859c398203d6962 Mon Sep 17 00:00:00 2001 From: Simon Zolin Date: Thu, 28 May 2020 17:14:50 +0300 Subject: [PATCH 01/11] + new query logs API + "upstream" + filteringStatusProcessed + ctDomainOrClient remove ctQuestionType, ctDomain, ctClient --- AGHTechDoc.md | 23 ++++++++++++++-------- querylog/json.go | 2 ++ querylog/qlog_http.go | 10 ++-------- querylog/qlog_test.go | 8 ++++---- querylog/search_criteria.go | 38 ++++++++++++++++--------------------- 5 files changed, 39 insertions(+), 42 deletions(-) diff --git a/AGHTechDoc.md b/AGHTechDoc.md index 5a3b001c958..ee9e7ee83d6 100644 --- a/AGHTechDoc.md +++ b/AGHTechDoc.md @@ -1200,8 +1200,8 @@ When a new DNS request is received and processed, we store information about thi "QH":"...", // target host name without the last dot "QT":"...", // question type "QC":"...", // question class - "Answer":"...", - "OrigAnswer":"...", + "Answer":"base64 data", + "OrigAnswer":"base64 data", "Result":{ "IsFiltered":true, "Reason":3, @@ -1234,16 +1234,22 @@ Request: GET /control/querylog ?older_than=2006-01-02T15:04:05.999999999Z07:00 - &filter_domain=... - &filter_client=... - &filter_question_type=A | AAAA - &filter_response_status= | filtered + &search=... + &response_status=""|blocked|whitelisted|processed `older_than` setting is used for paging. UI uses an empty value for `older_than` on the first request and gets the latest log entries. To get the older entries, UI sets `older_than` to the `oldest` value from the server's response. -If "filter" settings are set, server returns only entries that match the specified request. +If search settings are set, server returns only entries that match the specified request. -For `filter.domain` and `filter.client` the server matches substrings by default: `adguard.com` matches `www.adguard.com`. Strict matching can be enabled by enclosing the value in double quotes: `"adguard.com"` matches `adguard.com` but doesn't match `www.adguard.com`. +`search`: +match by domain name or client IP address. +The server matches substrings by default: e.g. `adguard.com` matches `www.adguard.com`. +Strict matching can be enabled by enclosing the value in double quotes: e.g. `"adguard.com"` matches `adguard.com` but doesn't match `www.adguard.com`. + +`response_status`: +* blocked: only blocked entries +* whitelisted: only white-listed entries +* processed: all not blocked, not white-listed entries Response: @@ -1266,6 +1272,7 @@ Response: } ... ], + "upstream":"...", // Upstream URL starting with tcp://, tls://, https://, or with an IP address "answer_dnssec": true, "client":"127.0.0.1", "elapsedMs":"0.098403", diff --git a/querylog/json.go b/querylog/json.go index 86f35e11138..cc7e6c391c3 100644 --- a/querylog/json.go +++ b/querylog/json.go @@ -112,6 +112,8 @@ func (l *queryLog) logEntryToJSONEntry(entry *logEntry) map[string]interface{} { } } + jsonEntry["upstream"] = entry.Upstream + return jsonEntry } diff --git a/querylog/qlog_http.go b/querylog/qlog_http.go index 19caa35cee5..cf804c4749b 100644 --- a/querylog/qlog_http.go +++ b/querylog/qlog_http.go @@ -142,10 +142,6 @@ func (l *queryLog) parseSearchCriteria(q url.Values, name string, ct criteriaTyp c.strict = true } - if ct == ctClient && l.conf.AnonymizeClientIP { - c.value = l.getClientIP(c.value) - } - if ct == ctFilteringStatus && !util.ContainsString(filteringStatusValues, c.value) { return false, c, fmt.Errorf("invalid value %s", c.value) } @@ -180,10 +176,8 @@ func (l *queryLog) parseSearchParams(r *http.Request) (*searchParams, error) { } paramNames := map[string]criteriaType{ - "filter_domain": ctDomain, - "filter_client": ctClient, - "filter_question_type": ctQuestionType, - "filter_response_status": ctFilteringStatus, + "search": ctDomainOrClient, + "response_status": ctFilteringStatus, } for k, v := range paramNames { diff --git a/querylog/qlog_test.go b/querylog/qlog_test.go index 921d2870f57..c087fa4d39c 100644 --- a/querylog/qlog_test.go +++ b/querylog/qlog_test.go @@ -57,7 +57,7 @@ func TestQueryLog(t *testing.T) { // search by domain (strict) params = newSearchParams() params.searchCriteria = append(params.searchCriteria, searchCriteria{ - criteriaType: ctDomain, + criteriaType: ctDomainOrClient, strict: true, value: "test.example.org", }) @@ -68,7 +68,7 @@ func TestQueryLog(t *testing.T) { // search by domain (not strict) params = newSearchParams() params.searchCriteria = append(params.searchCriteria, searchCriteria{ - criteriaType: ctDomain, + criteriaType: ctDomainOrClient, strict: false, value: "example.org", }) @@ -81,7 +81,7 @@ func TestQueryLog(t *testing.T) { // search by client IP (strict) params = newSearchParams() params.searchCriteria = append(params.searchCriteria, searchCriteria{ - criteriaType: ctClient, + criteriaType: ctDomainOrClient, strict: true, value: "2.2.2.2", }) @@ -92,7 +92,7 @@ func TestQueryLog(t *testing.T) { // search by client IP (part of) params = newSearchParams() params.searchCriteria = append(params.searchCriteria, searchCriteria{ - criteriaType: ctClient, + criteriaType: ctDomainOrClient, strict: false, value: "2.2.2", }) diff --git a/querylog/search_criteria.go b/querylog/search_criteria.go index b2ba63f6cce..bc2aa43537b 100644 --- a/querylog/search_criteria.go +++ b/querylog/search_criteria.go @@ -9,9 +9,7 @@ import ( type criteriaType int const ( - ctDomain criteriaType = iota // domain name - ctClient // client IP address - ctQuestionType // question type + ctDomainOrClient criteriaType = iota // domain name or client IP address ctFilteringStatus // filtering status ) @@ -25,6 +23,7 @@ const ( filteringStatusWhitelisted = "whitelisted" // whitelisted filteringStatusRewritten = "rewritten" // all kinds of rewrites filteringStatusSafeSearch = "safe_search" // enforced safe search + filteringStatusProcessed = "processed" // not blocked, not white-listed entries ) // filteringStatusValues -- array with all possible filteringStatus values @@ -32,6 +31,7 @@ var filteringStatusValues = []string{ filteringStatusAll, filteringStatusFiltered, filteringStatusBlocked, filteringStatusBlockedSafebrowsing, filteringStatusBlockedParental, filteringStatusWhitelisted, filteringStatusRewritten, filteringStatusSafeSearch, + filteringStatusProcessed, } // searchCriteria - every search request may contain a list of different search criteria @@ -48,12 +48,9 @@ func (c *searchCriteria) quickMatch(line string) bool { // note that we do this only for a limited set of criteria switch c.criteriaType { - case ctDomain: - return c.quickMatchJSONValue(line, "QH") - case ctClient: - return c.quickMatchJSONValue(line, "IP") - case ctQuestionType: - return c.quickMatchJSONValue(line, "QT") + case ctDomainOrClient: + return c.quickMatchJSONValue(line, "QH") || + c.quickMatchJSONValue(line, "IP") default: return true } @@ -80,29 +77,23 @@ func (c *searchCriteria) quickMatchJSONValue(line string, propertyName string) b // nolint (gocyclo) func (c *searchCriteria) match(entry *logEntry) bool { switch c.criteriaType { - case ctDomain: + case ctDomainOrClient: if c.strict && entry.QHost == c.value { return true } if !c.strict && strings.Contains(entry.QHost, c.value) { return true } - return false - case ctClient: + if c.strict && entry.IP == c.value { return true } if !c.strict && strings.Contains(entry.IP, c.value) { return true } + return false - case ctQuestionType: - if c.strict && entry.QType == c.value { - return true - } - if !c.strict && strings.Contains(entry.QType, c.value) { - return true - } + case ctFilteringStatus: res := entry.Result @@ -127,12 +118,15 @@ func (c *searchCriteria) match(entry *logEntry) bool { res.Reason == dnsfilter.RewriteEtcHosts) case filteringStatusSafeSearch: return res.IsFiltered && res.Reason == dnsfilter.FilteredSafeSearch + + case filteringStatusProcessed: + return !(res.Reason == dnsfilter.FilteredBlackList || + res.Reason == dnsfilter.FilteredBlockedService || + res.Reason == dnsfilter.NotFilteredWhiteList) + default: return false } - - default: - return false } return false From 0adbce5d385f233087f365028bb98f5772862b41 Mon Sep 17 00:00:00 2001 From: Simon Zolin Date: Thu, 28 May 2020 17:58:56 +0300 Subject: [PATCH 02/11] * openapi --- openapi/openapi.yaml | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/openapi/openapi.yaml b/openapi/openapi.yaml index 304c8dc59aa..f1a5b11ada1 100644 --- a/openapi/openapi.yaml +++ b/openapi/openapi.yaml @@ -163,29 +163,21 @@ paths: description: Limit the number of records to be returned schema: type: integer - - name: filter_domain + - name: search in: query - description: Filter by domain name + description: Filter by domain name or client IP schema: type: string - - name: filter_client - in: query - description: Filter by client - schema: - type: string - - name: filter_question_type - in: query - description: Filter by question type - schema: - type: string - - name: filter_response_status + - name: response_status in: query description: Filter by response status schema: type: string enum: - - null - - filtered + - "" + - blocked + - whitelisted + - processed responses: "200": description: OK @@ -1421,6 +1413,9 @@ components: description: Answer from upstream server (optional) items: $ref: "#/components/schemas/DnsAnswer" + upstream: + type: string + description: Upstream URL starting with tcp://, tls://, https://, or with an IP address answer_dnssec: type: boolean client: From 0904eeffa8ec75fb7342dae3ec5e0b11a8a7df1d Mon Sep 17 00:00:00 2001 From: Simon Zolin Date: Fri, 29 May 2020 11:15:22 +0300 Subject: [PATCH 03/11] + client_proto --- AGHTechDoc.md | 2 ++ dnsforward/stats.go | 5 +++++ querylog/decode.go | 3 +++ querylog/json.go | 9 +++++---- querylog/qlog.go | 9 ++++++--- querylog/querylog.go | 15 ++++++++------- 6 files changed, 29 insertions(+), 14 deletions(-) diff --git a/AGHTechDoc.md b/AGHTechDoc.md index ee9e7ee83d6..e5f120d7c64 100644 --- a/AGHTechDoc.md +++ b/AGHTechDoc.md @@ -1200,6 +1200,7 @@ When a new DNS request is received and processed, we store information about thi "QH":"...", // target host name without the last dot "QT":"...", // question type "QC":"...", // question class + "CP":"" | "doh", // client connection protocol "Answer":"base64 data", "OrigAnswer":"base64 data", "Result":{ @@ -1275,6 +1276,7 @@ Response: "upstream":"...", // Upstream URL starting with tcp://, tls://, https://, or with an IP address "answer_dnssec": true, "client":"127.0.0.1", + "client_proto": "" (plain) | "doh", "elapsedMs":"0.098403", "filterId":1, "question":{ diff --git a/dnsforward/stats.go b/dnsforward/stats.go index e9591abc3ee..3f3ee10c817 100644 --- a/dnsforward/stats.go +++ b/dnsforward/stats.go @@ -39,6 +39,11 @@ func processQueryLogsAndStats(ctx *dnsContext) int { Elapsed: elapsed, ClientIP: getIP(d.Addr), } + + if d.HTTPRequest != nil { + p.ClientProto = "doh" + } + if d.Upstream != nil { p.Upstream = d.Upstream.Address() } diff --git a/querylog/decode.go b/querylog/decode.go index 3f3811400f4..fc3f84ebf94 100644 --- a/querylog/decode.go +++ b/querylog/decode.go @@ -37,6 +37,9 @@ func decodeLogEntry(ent *logEntry, str string) { case "QC": ent.QClass = v + case "CP": + ent.ClientProto = v + case "Answer": ent.Answer, err = base64.StdEncoding.DecodeString(v) case "OrigAnswer": diff --git a/querylog/json.go b/querylog/json.go index cc7e6c391c3..a1a481f0efd 100644 --- a/querylog/json.go +++ b/querylog/json.go @@ -63,10 +63,11 @@ func (l *queryLog) logEntryToJSONEntry(entry *logEntry) map[string]interface{} { } jsonEntry := map[string]interface{}{ - "reason": entry.Result.Reason.String(), - "elapsedMs": strconv.FormatFloat(entry.Elapsed.Seconds()*1000, 'f', -1, 64), - "time": entry.Time.Format(time.RFC3339Nano), - "client": l.getClientIP(entry.IP), + "reason": entry.Result.Reason.String(), + "elapsedMs": strconv.FormatFloat(entry.Elapsed.Seconds()*1000, 'f', -1, 64), + "time": entry.Time.Format(time.RFC3339Nano), + "client": l.getClientIP(entry.IP), + "client_proto": entry.ClientProto, } jsonEntry["question"] = map[string]interface{}{ "host": entry.QHost, diff --git a/querylog/qlog.go b/querylog/qlog.go index 27bcc01eb7f..a5780ef1bec 100644 --- a/querylog/qlog.go +++ b/querylog/qlog.go @@ -38,6 +38,8 @@ type logEntry struct { QType string `json:"QT"` QClass string `json:"QC"` + ClientProto string `json:"CP"` // "" or "doh" + Answer []byte `json:",omitempty"` // sometimes empty answers happen like binerdunt.top or rev2.globalrootservers.net OrigAnswer []byte `json:",omitempty"` @@ -119,9 +121,10 @@ func (l *queryLog) Add(params AddParams) { IP: l.getClientIP(params.ClientIP.String()), Time: now, - Result: *params.Result, - Elapsed: params.Elapsed, - Upstream: params.Upstream, + Result: *params.Result, + Elapsed: params.Elapsed, + Upstream: params.Upstream, + ClientProto: params.ClientProto, } q := params.Question.Question[0] entry.QHost = strings.ToLower(q.Name[:len(q.Name)-1]) // remove the last dot diff --git a/querylog/querylog.go b/querylog/querylog.go index 2fa7ac9d339..5431ef1e087 100644 --- a/querylog/querylog.go +++ b/querylog/querylog.go @@ -41,13 +41,14 @@ type Config struct { // AddParams - parameters for Add() type AddParams struct { - Question *dns.Msg - Answer *dns.Msg // The response we sent to the client (optional) - OrigAnswer *dns.Msg // The response from an upstream server (optional) - Result *dnsfilter.Result // Filtering result (optional) - Elapsed time.Duration // Time spent for processing the request - ClientIP net.IP - Upstream string + Question *dns.Msg + Answer *dns.Msg // The response we sent to the client (optional) + OrigAnswer *dns.Msg // The response from an upstream server (optional) + Result *dnsfilter.Result // Filtering result (optional) + Elapsed time.Duration // Time spent for processing the request + ClientIP net.IP + Upstream string // Upstream server URL + ClientProto string // Protocol for the client connection: "" (plain), "doh" } // New - create a new instance of the query log From d971bb9957a6ec28a61cfbfc5fa5111fec71efa6 Mon Sep 17 00:00:00 2001 From: Simon Zolin Date: Fri, 29 May 2020 11:15:31 +0300 Subject: [PATCH 04/11] * minor --- dnsforward/dnsforward_http.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/dnsforward/dnsforward_http.go b/dnsforward/dnsforward_http.go index c2c94061f25..5f916a3fc44 100644 --- a/dnsforward/dnsforward_http.go +++ b/dnsforward/dnsforward_http.go @@ -385,6 +385,11 @@ func checkDNS(input string, bootstrap []string) error { return nil } +// Control flow: +// web +// -> dnsforward.handleDOH -> dnsforward.ServeHTTP +// -> proxy.ServeHTTP -> proxy.handleDNSRequest +// -> dnsforward.handleDNSRequest func (s *Server) handleDOH(w http.ResponseWriter, r *http.Request) { if !s.conf.TLSAllowUnencryptedDOH && r.TLS == nil { httpError(r, w, http.StatusNotFound, "Not Found") From 78648649fe2e2e944d87e8e25db0c0dcc4e15c7e Mon Sep 17 00:00:00 2001 From: Simon Zolin Date: Fri, 29 May 2020 11:19:31 +0300 Subject: [PATCH 05/11] openapi --- openapi/openapi.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openapi/openapi.yaml b/openapi/openapi.yaml index f1a5b11ada1..94eb6717558 100644 --- a/openapi/openapi.yaml +++ b/openapi/openapi.yaml @@ -1421,6 +1421,8 @@ components: client: type: string example: 192.168.0.1 + client_proto: + type: string elapsedMs: type: string example: "54.023928" From bccb9393464cb6ac897bb0e34e21c340dcf54a87 Mon Sep 17 00:00:00 2001 From: Simon Zolin Date: Fri, 29 May 2020 11:46:37 +0300 Subject: [PATCH 06/11] + "dot" --- AGHTechDoc.md | 2 +- dnsforward/stats.go | 4 +++- openapi/openapi.yaml | 5 ++++- querylog/querylog.go | 2 +- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/AGHTechDoc.md b/AGHTechDoc.md index e5f120d7c64..cc20d60a4ff 100644 --- a/AGHTechDoc.md +++ b/AGHTechDoc.md @@ -1276,7 +1276,7 @@ Response: "upstream":"...", // Upstream URL starting with tcp://, tls://, https://, or with an IP address "answer_dnssec": true, "client":"127.0.0.1", - "client_proto": "" (plain) | "doh", + "client_proto": "" (plain) | "doh" | "dot", "elapsedMs":"0.098403", "filterId":1, "question":{ diff --git a/dnsforward/stats.go b/dnsforward/stats.go index 3f3ee10c817..231ead780b1 100644 --- a/dnsforward/stats.go +++ b/dnsforward/stats.go @@ -40,8 +40,10 @@ func processQueryLogsAndStats(ctx *dnsContext) int { ClientIP: getIP(d.Addr), } - if d.HTTPRequest != nil { + if d.Proto == "https" { p.ClientProto = "doh" + } else if d.Proto == "tls" { + p.ClientProto = "dot" } if d.Upstream != nil { diff --git a/openapi/openapi.yaml b/openapi/openapi.yaml index 94eb6717558..858ae73596a 100644 --- a/openapi/openapi.yaml +++ b/openapi/openapi.yaml @@ -1422,7 +1422,10 @@ components: type: string example: 192.168.0.1 client_proto: - type: string + enum: + - dot + - doh + - "" elapsedMs: type: string example: "54.023928" diff --git a/querylog/querylog.go b/querylog/querylog.go index 5431ef1e087..7f6b4c87efc 100644 --- a/querylog/querylog.go +++ b/querylog/querylog.go @@ -48,7 +48,7 @@ type AddParams struct { Elapsed time.Duration // Time spent for processing the request ClientIP net.IP Upstream string // Upstream server URL - ClientProto string // Protocol for the client connection: "" (plain), "doh" + ClientProto string // Protocol for the client connection: "" (plain), "doh", "dot" } // New - create a new instance of the query log From 6a0194c7a184b7f4b10b71d9b531efb59056c548 Mon Sep 17 00:00:00 2001 From: Simon Zolin Date: Thu, 11 Jun 2020 15:39:54 +0300 Subject: [PATCH 07/11] fix whois test --- home/whois_test.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/home/whois_test.go b/home/whois_test.go index 75af9f14114..da93426f9f3 100644 --- a/home/whois_test.go +++ b/home/whois_test.go @@ -27,9 +27,9 @@ func TestWhois(t *testing.T) { w := Whois{timeoutMsec: 5000} resp, err := w.queryAll("8.8.8.8") - assert.True(t, err == nil) + assert.Nil(t, err) m := whoisParse(resp) - assert.True(t, m["orgname"] == "Google LLC") - assert.True(t, m["country"] == "US") - assert.True(t, m["city"] == "Mountain View") + assert.Equal(t, "Google LLC", m["orgname"]) + assert.Equal(t, "US", m["country"]) + assert.Equal(t, "Mountain View", m["city"]) } From b6052a4cd1c11f5f34db23781138eb7b6cb710f7 Mon Sep 17 00:00:00 2001 From: Simon Zolin Date: Tue, 16 Jun 2020 11:14:04 +0300 Subject: [PATCH 08/11] doc --- AGHTechDoc.md | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/AGHTechDoc.md b/AGHTechDoc.md index cc20d60a4ff..b2f4ab734b3 100644 --- a/AGHTechDoc.md +++ b/AGHTechDoc.md @@ -1236,7 +1236,7 @@ Request: GET /control/querylog ?older_than=2006-01-02T15:04:05.999999999Z07:00 &search=... - &response_status=""|blocked|whitelisted|processed + &response_status="..." `older_than` setting is used for paging. UI uses an empty value for `older_than` on the first request and gets the latest log entries. To get the older entries, UI sets `older_than` to the `oldest` value from the server's response. @@ -1248,9 +1248,15 @@ The server matches substrings by default: e.g. `adguard.com` matches `www.adguar Strict matching can be enabled by enclosing the value in double quotes: e.g. `"adguard.com"` matches `adguard.com` but doesn't match `www.adguard.com`. `response_status`: -* blocked: only blocked entries -* whitelisted: only white-listed entries -* processed: all not blocked, not white-listed entries +* all +* filtered - all kinds of filtering +* blocked - blocked or blocked service +* blocked_safebrowsing - blocked by safebrowsing +* blocked_parental - blocked by parental control +* whitelisted - whitelisted +* rewritten - all kinds of rewrites +* safe_search - enforced safe search +* processed - not blocked, not white-listed entries Response: From 15e714350cf7dfa3ed39ff2a02a083fa1f4fa46d Mon Sep 17 00:00:00 2001 From: Simon Zolin Date: Tue, 16 Jun 2020 11:47:26 +0300 Subject: [PATCH 09/11] fix search by "whitelisted", "rewritten" --- querylog/search_criteria.go | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/querylog/search_criteria.go b/querylog/search_criteria.go index bc2aa43537b..3c1ee0de738 100644 --- a/querylog/search_criteria.go +++ b/querylog/search_criteria.go @@ -101,7 +101,10 @@ func (c *searchCriteria) match(entry *logEntry) bool { case filteringStatusAll: return true case filteringStatusFiltered: - return res.IsFiltered + return res.IsFiltered || + res.Reason == dnsfilter.NotFilteredWhiteList || + res.Reason == dnsfilter.ReasonRewrite || + res.Reason == dnsfilter.RewriteEtcHosts case filteringStatusBlocked: return res.IsFiltered && (res.Reason == dnsfilter.FilteredBlackList || @@ -111,11 +114,10 @@ func (c *searchCriteria) match(entry *logEntry) bool { case filteringStatusBlockedSafebrowsing: return res.IsFiltered && res.Reason == dnsfilter.FilteredSafeBrowsing case filteringStatusWhitelisted: - return res.IsFiltered && res.Reason == dnsfilter.NotFilteredWhiteList + return res.Reason == dnsfilter.NotFilteredWhiteList case filteringStatusRewritten: - return res.IsFiltered && - (res.Reason == dnsfilter.ReasonRewrite || - res.Reason == dnsfilter.RewriteEtcHosts) + return (res.Reason == dnsfilter.ReasonRewrite || + res.Reason == dnsfilter.RewriteEtcHosts) case filteringStatusSafeSearch: return res.IsFiltered && res.Reason == dnsfilter.FilteredSafeSearch From bbc4eda39e7bda7f2f476aab75e16ccd4e91c01b Mon Sep 17 00:00:00 2001 From: Simon Zolin Date: Tue, 16 Jun 2020 12:10:17 +0300 Subject: [PATCH 10/11] If there are no more older entries, `"oldest":""` is returned. --- AGHTechDoc.md | 2 ++ querylog/querylog_search.go | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/AGHTechDoc.md b/AGHTechDoc.md index b2f4ab734b3..ad9854d312c 100644 --- a/AGHTechDoc.md +++ b/AGHTechDoc.md @@ -1302,6 +1302,8 @@ Response: The most recent entries are at the top of list. +If there are no more older entries, `"oldest":""` is returned. + ### API: Set querylog parameters diff --git a/querylog/querylog_search.go b/querylog/querylog_search.go index eda1f92d869..afa8afc2b36 100644 --- a/querylog/querylog_search.go +++ b/querylog/querylog_search.go @@ -129,7 +129,9 @@ func (l *queryLog) searchFiles(params *searchParams) ([]*logEntry, time.Time, in } } - oldest = time.Unix(0, oldestNano) + if oldestNano != 0 { + oldest = time.Unix(0, oldestNano) + } return entries, oldest, total } From 59c4a2886a97143e3a36912ec895dc1a06be88cc Mon Sep 17 00:00:00 2001 From: Simon Zolin Date: Tue, 16 Jun 2020 12:12:32 +0300 Subject: [PATCH 11/11] openapi --- openapi/openapi.yaml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/openapi/openapi.yaml b/openapi/openapi.yaml index 858ae73596a..13e330eb1dc 100644 --- a/openapi/openapi.yaml +++ b/openapi/openapi.yaml @@ -174,9 +174,14 @@ paths: schema: type: string enum: - - "" + - all + - filtered - blocked + - blocked_safebrowsing + - blocked_parental - whitelisted + - rewritten + - safe_search - processed responses: "200":