Merge branch 'master' into ADG-9415

This commit is contained in:
Ildar Kamalov
2025-01-29 15:30:03 +03:00
59 changed files with 2378 additions and 2684 deletions

View File

@@ -1,7 +1,7 @@
'name': 'build' 'name': 'build'
'env': 'env':
'GO_VERSION': '1.23.4' 'GO_VERSION': '1.23.5'
'NODE_VERSION': '16' 'NODE_VERSION': '16'
'on': 'on':

View File

@@ -1,7 +1,7 @@
'name': 'lint' 'name': 'lint'
'env': 'env':
'GO_VERSION': '1.23.4' 'GO_VERSION': '1.23.5'
'on': 'on':
'push': 'push':

25
.markdownlint.json Normal file
View File

@@ -0,0 +1,25 @@
{
"ul-indent": {
"indent": 4
},
"ul-style": {
"style": "dash"
},
"emphasis-style": {
"style": "asterisk"
},
"no-duplicate-heading": {
"siblings_only": true
},
"no-inline-html": {
"allowed_elements": [
"a"
]
},
"no-trailing-spaces": {
"br_spaces": 0
},
"line-length": false,
"no-bare-urls": false,
"link-fragments": false
}

File diff suppressed because it is too large Load Diff

View File

@@ -27,7 +27,7 @@ DIST_DIR = dist
GOAMD64 = v1 GOAMD64 = v1
GOPROXY = https://proxy.golang.org|direct GOPROXY = https://proxy.golang.org|direct
GOTELEMETRY = off GOTELEMETRY = off
GOTOOLCHAIN = go1.23.4 GOTOOLCHAIN = go1.23.5
GPG_KEY = devteam@adguard.com GPG_KEY = devteam@adguard.com
GPG_KEY_PASSPHRASE = not-a-real-password GPG_KEY_PASSPHRASE = not-a-real-password
NPM = npm NPM = npm

View File

@@ -8,7 +8,7 @@
'variables': 'variables':
'channel': 'edge' 'channel': 'edge'
'dockerFrontend': 'adguard/home-js-builder:2.0' 'dockerFrontend': 'adguard/home-js-builder:2.0'
'dockerGo': 'adguard/go-builder:1.23.4--1' 'dockerGo': 'adguard/go-builder:1.23.5--1'
'stages': 'stages':
- 'Build frontend': - 'Build frontend':
@@ -278,7 +278,7 @@
'variables': 'variables':
'channel': 'beta' 'channel': 'beta'
'dockerFrontend': 'adguard/home-js-builder:2.0' 'dockerFrontend': 'adguard/home-js-builder:2.0'
'dockerGo': 'adguard/go-builder:1.23.4--1' 'dockerGo': 'adguard/go-builder:1.23.5--1'
# release-vX.Y.Z branches are the branches from which the actual final # release-vX.Y.Z branches are the branches from which the actual final
# release is built. # release is built.
- '^release-v[0-9]+\.[0-9]+\.[0-9]+': - '^release-v[0-9]+\.[0-9]+\.[0-9]+':
@@ -294,4 +294,4 @@
'variables': 'variables':
'channel': 'release' 'channel': 'release'
'dockerFrontend': 'adguard/home-js-builder:2.0' 'dockerFrontend': 'adguard/home-js-builder:2.0'
'dockerGo': 'adguard/go-builder:1.23.4--1' 'dockerGo': 'adguard/go-builder:1.23.5--1'

View File

@@ -6,7 +6,7 @@
'name': 'AdGuard Home - Build and run tests' 'name': 'AdGuard Home - Build and run tests'
'variables': 'variables':
'dockerFrontend': 'adguard/home-js-builder:2.0' 'dockerFrontend': 'adguard/home-js-builder:2.0'
'dockerGo': 'adguard/go-builder:1.23.4--1' 'dockerGo': 'adguard/go-builder:1.23.5--1'
'channel': 'development' 'channel': 'development'
'stages': 'stages':
@@ -196,5 +196,5 @@
# may need to build a few of these. # may need to build a few of these.
'variables': 'variables':
'dockerFrontend': 'adguard/home-js-builder:2.0' 'dockerFrontend': 'adguard/home-js-builder:2.0'
'dockerGo': 'adguard/go-builder:1.23.4--1' 'dockerGo': 'adguard/go-builder:1.23.5--1'
'channel': 'candidate' 'channel': 'candidate'

View File

@@ -166,7 +166,7 @@
"encryption_settings": "Encryptie instellingen", "encryption_settings": "Encryptie instellingen",
"dhcp_settings": "DHCP instellingen", "dhcp_settings": "DHCP instellingen",
"upstream_dns": "Upstream DNS-servers", "upstream_dns": "Upstream DNS-servers",
"upstream_dns_help": "Een server-adres per regel invoeren. <a>Meer weten</a> over het configureren van upstream DNS-servers.", "upstream_dns_help": "Een server-adres per regel invoeren. <a>Meer informatie</a> over het configureren van upstream DNS-servers.",
"upstream_dns_configured_in_file": "Geconfigureerd in {{path}}", "upstream_dns_configured_in_file": "Geconfigureerd in {{path}}",
"test_upstream_btn": "Test upstream", "test_upstream_btn": "Test upstream",
"upstreams": "Upstreams", "upstreams": "Upstreams",

View File

@@ -20,7 +20,7 @@
"resolve_clients_title": "Увімкнути зворотне вирішення IP-адрес клієнтів", "resolve_clients_title": "Увімкнути зворотне вирішення IP-адрес клієнтів",
"resolve_clients_desc": "Визначати доменні імена клієнтів за допомогою PTR-запитів до відповідних серверів — приватних DNS-серверів для локальних клієнтів та upstream-серверів для клієнтів з публічними IP-адресами.", "resolve_clients_desc": "Визначати доменні імена клієнтів за допомогою PTR-запитів до відповідних серверів — приватних DNS-серверів для локальних клієнтів та upstream-серверів для клієнтів з публічними IP-адресами.",
"use_private_ptr_resolvers_title": "Використовувати приватні зворотні DNS-резолвери", "use_private_ptr_resolvers_title": "Використовувати приватні зворотні DNS-резолвери",
"use_private_ptr_resolvers_desc": "Надсилати зворотні DNS-запити до вказаних серверів для клієнтів, що обслуговуються локально. Якщо вимкнено, AdGuard Home буде відповідати NXDOMAIN на всі такі PTR-запити, окрім запитів про клієнтів, що уже відомі завдяки DHCP, /etc/hosts тощо.", "use_private_ptr_resolvers_desc": "Розвʼязувати запити PTR, SOA та NS для доменів ARPA, що містять приватні IP-адреси, через приватні вихідні сервери, DHCP, /etc/hosts тощо. Якщо вимкнено, AdGuard Home відповідатиме на всі такі запити з NXDOMAIN.",
"check_dhcp_servers": "Перевірити DHCP-сервери", "check_dhcp_servers": "Перевірити DHCP-сервери",
"save_config": "Зберегти конфігурацію", "save_config": "Зберегти конфігурацію",
"enabled_dhcp": "DHCP-сервер увімкнено", "enabled_dhcp": "DHCP-сервер увімкнено",
@@ -343,10 +343,10 @@
"known_tracker": "Відомі трекери", "known_tracker": "Відомі трекери",
"install_welcome_title": "Вітаємо в AdGuard Home!", "install_welcome_title": "Вітаємо в AdGuard Home!",
"install_welcome_desc": "AdGuard Home — це мережевий DNS-сервер, що блокує рекламу та відстеження. Його мета — надати вам контроль над усією мережею та всіма пристроями в ній без потреби використання програми на стороні клієнта.", "install_welcome_desc": "AdGuard Home — це мережевий DNS-сервер, що блокує рекламу та відстеження. Його мета — надати вам контроль над усією мережею та всіма пристроями в ній без потреби використання програми на стороні клієнта.",
"install_settings_title": "Веб-інтерфейс адміністратора", "install_settings_title": "Вебінтерфейс адміністратора",
"install_settings_listen": "Мережевий інтерфейс", "install_settings_listen": "Мережевий інтерфейс",
"install_settings_port": "Порт", "install_settings_port": "Порт",
"install_settings_interface_link": "Веб-інтерфейс адміністратора AdGuard Home буде доступний за такими адресами:", "install_settings_interface_link": "Вебінтерфейс адміністратора AdGuard Home буде доступний за такими адресами:",
"form_error_port": "Уведіть правильне значення порту", "form_error_port": "Уведіть правильне значення порту",
"install_settings_dns": "DNS-сервер", "install_settings_dns": "DNS-сервер",
"install_settings_dns_desc": "Вам потрібно буде налаштувати свої пристрої або маршрутизатор для використання DNS-сервера за такими адресами:", "install_settings_dns_desc": "Вам потрібно буде налаштувати свої пристрої або маршрутизатор для використання DNS-сервера за такими адресами:",

View File

@@ -20,7 +20,7 @@
"resolve_clients_title": "啟用用戶端的 IP 位址之反向的解析", "resolve_clients_title": "啟用用戶端的 IP 位址之反向的解析",
"resolve_clients_desc": "透過傳送指標PTR查詢到對應的解析器私人 DNS 伺服器供區域的用戶端,上游的伺服器供有公共 IP 位址的用戶端),反向地解析用戶端的 IP 位址變為它們的主機名稱。", "resolve_clients_desc": "透過傳送指標PTR查詢到對應的解析器私人 DNS 伺服器供區域的用戶端,上游的伺服器供有公共 IP 位址的用戶端),反向地解析用戶端的 IP 位址變為它們的主機名稱。",
"use_private_ptr_resolvers_title": "使用私人反向的 DNS 解析器", "use_private_ptr_resolvers_title": "使用私人反向的 DNS 解析器",
"use_private_ptr_resolvers_desc": "使用私人上游伺服器、DHCP、/etc/hosts 等方式解析包含私人 IP 位址的 ARPA 網域 PTR、SOA 和 NS 請求。如果禁用AdGuard Home 將對所有此類請求以 NXDOMAIN 回。", "use_private_ptr_resolvers_desc": "通過私人上游伺服器、DHCP、/etc/hosts 等等,對包含私人 IP 位址的 ARPA 網域解析 PTR、SOA 和 NS 請求。如果禁用AdGuard Home 將對所有此類請求以 NXDOMAIN 回。",
"check_dhcp_servers": "檢查動態主機設定協定DHCP伺服器", "check_dhcp_servers": "檢查動態主機設定協定DHCP伺服器",
"save_config": "儲存配置", "save_config": "儲存配置",
"enabled_dhcp": "動態主機設定協定DHCP伺服器被啟用", "enabled_dhcp": "動態主機設定協定DHCP伺服器被啟用",

View File

@@ -46,7 +46,7 @@ export const getStats = () => async (dispatch: any) => {
const normalizedTopClients = normalizeTopStats(stats.top_clients); const normalizedTopClients = normalizeTopStats(stats.top_clients);
const clientsParams = getParamsForClientsSearch(normalizedTopClients, 'name'); const clientsParams = getParamsForClientsSearch(normalizedTopClients, 'name');
const clients = await apiClient.findClients(clientsParams); const clients = await apiClient.searchClients(clientsParams);
const topClientsWithInfo = addClientInfo(normalizedTopClients, clients, 'name'); const topClientsWithInfo = addClientInfo(normalizedTopClients, clients, 'name');
const normalizedStats = { const normalizedStats = {

View File

@@ -415,7 +415,7 @@ class Api {
// Per-client settings // Per-client settings
GET_CLIENTS = { path: 'clients', method: 'GET' }; GET_CLIENTS = { path: 'clients', method: 'GET' };
FIND_CLIENTS = { path: 'clients/find', method: 'GET' }; SEARCH_CLIENTS = { path: 'clients/search', method: 'POST' };
ADD_CLIENT = { path: 'clients/add', method: 'POST' }; ADD_CLIENT = { path: 'clients/add', method: 'POST' };
@@ -453,11 +453,12 @@ class Api {
return this.makeRequest(path, method, parameters); return this.makeRequest(path, method, parameters);
} }
findClients(params: any) { searchClients(config: any) {
const { path, method } = this.FIND_CLIENTS; const { path, method } = this.SEARCH_CLIENTS;
const url = getPathWithQueryString(path, params); const parameters = {
data: config,
return this.makeRequest(url, method); };
return this.makeRequest(path, method, parameters);
} }
// DNS access settings // DNS access settings

View File

@@ -23,7 +23,7 @@ interface RowProps {
const Row = ({ label, count, response_status, tooltipTitle, translationComponents }: RowProps) => { const Row = ({ label, count, response_status, tooltipTitle, translationComponents }: RowProps) => {
const content = response_status ? ( const content = response_status ? (
<LogsSearchLink response_status={response_status}>{formatNumber(count)}</LogsSearchLink> <LogsSearchLink response_status={response_status}>{count}</LogsSearchLink>
) : ( ) : (
count count
); );
@@ -77,16 +77,16 @@ const Counters = ({ refreshButton, subtitle }: CountersProps) => {
? t('number_of_dns_query_hours', { count: msToHours(interval) }) ? t('number_of_dns_query_hours', { count: msToHours(interval) })
: t('number_of_dns_query_days', { count: msToDays(interval) }); : t('number_of_dns_query_days', { count: msToDays(interval) });
const rows = [ const rows: RowProps[] = [
{ {
label: 'dns_query', label: 'dns_query',
count: numDnsQueries.toString(), count: formatNumber(numDnsQueries),
tooltipTitle: dnsQueryTooltip, tooltipTitle: dnsQueryTooltip,
response_status: RESPONSE_FILTER.ALL.QUERY, response_status: RESPONSE_FILTER.ALL.QUERY,
}, },
{ {
label: 'blocked_by', label: 'blocked_by',
count: numBlockedFiltering.toString(), count: formatNumber(numBlockedFiltering),
tooltipTitle: 'number_of_dns_query_blocked_24_hours', tooltipTitle: 'number_of_dns_query_blocked_24_hours',
response_status: RESPONSE_FILTER.BLOCKED.QUERY, response_status: RESPONSE_FILTER.BLOCKED.QUERY,
@@ -98,19 +98,19 @@ const Counters = ({ refreshButton, subtitle }: CountersProps) => {
}, },
{ {
label: 'stats_malware_phishing', label: 'stats_malware_phishing',
count: numReplacedSafebrowsing.toString(), count: formatNumber(numReplacedSafebrowsing),
tooltipTitle: 'number_of_dns_query_blocked_24_hours_by_sec', tooltipTitle: 'number_of_dns_query_blocked_24_hours_by_sec',
response_status: RESPONSE_FILTER.BLOCKED_THREATS.QUERY, response_status: RESPONSE_FILTER.BLOCKED_THREATS.QUERY,
}, },
{ {
label: 'stats_adult', label: 'stats_adult',
count: numReplacedParental.toString(), count: formatNumber(numReplacedParental),
tooltipTitle: 'number_of_dns_query_blocked_24_hours_adult', tooltipTitle: 'number_of_dns_query_blocked_24_hours_adult',
response_status: RESPONSE_FILTER.BLOCKED_ADULT_WEBSITES.QUERY, response_status: RESPONSE_FILTER.BLOCKED_ADULT_WEBSITES.QUERY,
}, },
{ {
label: 'enforced_save_search', label: 'enforced_save_search',
count: numReplacedSafesearch.toString(), count: formatNumber(numReplacedSafesearch),
tooltipTitle: 'number_of_dns_query_to_safe_search', tooltipTitle: 'number_of_dns_query_to_safe_search',
response_status: RESPONSE_FILTER.SAFE_SEARCH.QUERY, response_status: RESPONSE_FILTER.SAFE_SEARCH.QUERY,
}, },

View File

@@ -154,7 +154,7 @@ const Dashboard = ({
}} }}
disabled={processingProtection}> disabled={processingProtection}>
{protectionDisabledDuration {protectionDisabledDuration
? `${t('enable_protection_timer')} ${getRemaningTimeText(protectionDisabledDuration)}` ? `${t('enable_protection_timer', { time: getRemaningTimeText(protectionDisabledDuration) })}`
: getProtectionBtnText(protectionEnabled)} : getProtectionBtnText(protectionEnabled)}
</button> </button>

View File

@@ -312,7 +312,7 @@ const ClientsTable = ({
return content; return content;
} }
return <LogsSearchLink search={row.original.ids[0]}>{content}</LogsSearchLink>; return <LogsSearchLink search={row.original.name}>{content}</LogsSearchLink>;
}, },
}, },
{ {

View File

@@ -451,13 +451,10 @@ export const getParamsForClientsSearch = (data: any, param: any, additionalParam
clients.add(e[additionalParam]); clients.add(e[additionalParam]);
} }
}); });
const params = {};
const ids = Array.from(clients.values());
ids.forEach((id, i) => {
params[`ip${i}`] = id;
});
return params; return {
clients: Array.from(clients).map(id => ({ id })),
};
}; };
/** /**
@@ -524,7 +521,7 @@ export const getObjDiff = (initialValues: any, values: any) =>
* @param num {number} to format * @param num {number} to format
* @returns {string} Returns a string with a language-sensitive representation of this number * @returns {string} Returns a string with a language-sensitive representation of this number
*/ */
export const formatNumber = (num: any) => { export const formatNumber = (num: number): string => {
const currentLanguage = i18n.languages[0] || DEFAULT_LANGUAGE; const currentLanguage = i18n.languages[0] || DEFAULT_LANGUAGE;
return num.toLocaleString(currentLanguage); return num.toLocaleString(currentLanguage);
}; };

View File

@@ -1,5 +1,5 @@
{ {
"timeUpdated": "2024-12-03T12:12:08.316Z", "timeUpdated": "2025-01-13T10:04:54.031Z",
"categories": { "categories": {
"0": "audio_video_player", "0": "audio_video_player",
"1": "comments", "1": "comments",
@@ -9772,6 +9772,13 @@
"url": "http://www.jetinteractive.com.au/", "url": "http://www.jetinteractive.com.au/",
"companyId": "jet_interactive" "companyId": "jet_interactive"
}, },
"jetbrains": {
"name": "JetBrains",
"categoryId": 8,
"url": "https://www.jetbrains.com/",
"companyId": "jetbrains",
"source": "AdGuard"
},
"jetlore": { "jetlore": {
"name": "Jetlore", "name": "Jetlore",
"categoryId": 6, "categoryId": 6,
@@ -22410,6 +22417,7 @@
"adservice.google.pl": "google_marketing", "adservice.google.pl": "google_marketing",
"adservice.google.ru": "google_marketing", "adservice.google.ru": "google_marketing",
"adservice.google.vg": "google_marketing", "adservice.google.vg": "google_marketing",
"adtrafficquality.google": "google_marketing",
"dai.google.com": "google_marketing", "dai.google.com": "google_marketing",
"doubleclickbygoogle.com": "google_marketing", "doubleclickbygoogle.com": "google_marketing",
"googlesyndication-cn.com": "google_marketing", "googlesyndication-cn.com": "google_marketing",
@@ -22763,6 +22771,22 @@
"jeeng.com": "jeeng", "jeeng.com": "jeeng",
"api.jeeng.com": "jeeng_widgets", "api.jeeng.com": "jeeng_widgets",
"phone-analytics.com": "jet_interactive", "phone-analytics.com": "jet_interactive",
"grazie.ai": "jetbrains",
"intellij.net": "jetbrains",
"jb.gg": "jetbrains",
"jetbrains.ai": "jetbrains",
"jetbrains.com": "jetbrains",
"jetbrains.com.cn": "jetbrains",
"jetbrains.dev": "jetbrains",
"jetbrains.net": "jetbrains",
"jetbrains.org": "jetbrains",
"jetbrains.ru": "jetbrains",
"jetbrains.space": "jetbrains",
"kotl.in": "jetbrains",
"kotlinconf.com": "jetbrains",
"kotlinlang.org": "jetbrains",
"myjetbrains.com": "jetbrains",
"talkingkotlin.com": "jetbrains",
"jetlore.com": "jetlore", "jetlore.com": "jetlore",
"pixel.wp.com": "jetpack", "pixel.wp.com": "jetpack",
"stats.wp.com": "jetpack", "stats.wp.com": "jetpack",

24
go.mod
View File

@@ -1,10 +1,10 @@
module github.com/AdguardTeam/AdGuardHome module github.com/AdguardTeam/AdGuardHome
go 1.23.4 go 1.23.5
require ( require (
github.com/AdguardTeam/dnsproxy v0.73.4 github.com/AdguardTeam/dnsproxy v0.73.5
github.com/AdguardTeam/golibs v0.30.5 github.com/AdguardTeam/golibs v0.31.0
github.com/AdguardTeam/urlfilter v0.20.0 github.com/AdguardTeam/urlfilter v0.20.0
github.com/NYTimes/gziphandler v1.1.1 github.com/NYTimes/gziphandler v1.1.1
github.com/ameshkov/dnscrypt/v2 v2.3.0 github.com/ameshkov/dnscrypt/v2 v2.3.0
@@ -19,7 +19,7 @@ require (
github.com/google/gopacket v1.1.19 github.com/google/gopacket v1.1.19
github.com/google/renameio/v2 v2.0.0 github.com/google/renameio/v2 v2.0.0
github.com/google/uuid v1.6.0 github.com/google/uuid v1.6.0
github.com/insomniacslk/dhcp v0.0.0-20240829085014-a3a4c1f04475 github.com/insomniacslk/dhcp v0.0.0-20241203100832-a481575ed0ef
github.com/josharian/native v1.1.1-0.20230202152459-5c7d0dd6ab86 github.com/josharian/native v1.1.1-0.20230202152459-5c7d0dd6ab86
github.com/kardianos/service v1.2.2 github.com/kardianos/service v1.2.2
github.com/mdlayher/ethernet v0.0.0-20220221185849-529eae5b6118 github.com/mdlayher/ethernet v0.0.0-20220221185849-529eae5b6118
@@ -33,9 +33,9 @@ require (
github.com/stretchr/testify v1.10.0 github.com/stretchr/testify v1.10.0
github.com/ti-mo/netfilter v0.5.2 github.com/ti-mo/netfilter v0.5.2
go.etcd.io/bbolt v1.3.11 go.etcd.io/bbolt v1.3.11
golang.org/x/crypto v0.29.0 golang.org/x/crypto v0.31.0
golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f golang.org/x/exp v0.0.0-20241217172543-b2144cdd0a67
golang.org/x/net v0.31.0 golang.org/x/net v0.33.0
golang.org/x/sys v0.28.0 golang.org/x/sys v0.28.0
gopkg.in/natefinch/lumberjack.v2 v2.2.1 gopkg.in/natefinch/lumberjack.v2 v2.2.1
gopkg.in/yaml.v3 v3.0.1 gopkg.in/yaml.v3 v3.0.1
@@ -49,9 +49,9 @@ require (
github.com/beefsack/go-rate v0.0.0-20220214233405-116f4ca011a0 // indirect github.com/beefsack/go-rate v0.0.0-20220214233405-116f4ca011a0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
github.com/google/pprof v0.0.0-20241101162523-b92577c0c142 // indirect github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad // indirect
github.com/mdlayher/socket v0.5.1 // indirect github.com/mdlayher/socket v0.5.1 // indirect
github.com/onsi/ginkgo/v2 v2.21.0 // indirect github.com/onsi/ginkgo/v2 v2.22.1 // indirect
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
github.com/pierrec/lz4/v4 v4.1.21 // indirect github.com/pierrec/lz4/v4 v4.1.21 // indirect
github.com/pkg/errors v0.9.1 // indirect github.com/pkg/errors v0.9.1 // indirect
@@ -60,8 +60,8 @@ require (
github.com/u-root/uio v0.0.0-20240224005618-d2acac8f3701 // indirect github.com/u-root/uio v0.0.0-20240224005618-d2acac8f3701 // indirect
go.uber.org/mock v0.5.0 // indirect go.uber.org/mock v0.5.0 // indirect
golang.org/x/mod v0.22.0 // indirect golang.org/x/mod v0.22.0 // indirect
golang.org/x/sync v0.9.0 // indirect golang.org/x/sync v0.10.0 // indirect
golang.org/x/text v0.20.0 // indirect golang.org/x/text v0.21.0 // indirect
golang.org/x/tools v0.27.0 // indirect golang.org/x/tools v0.28.0 // indirect
gonum.org/v1/gonum v0.15.1 // indirect gonum.org/v1/gonum v0.15.1 // indirect
) )

52
go.sum
View File

@@ -1,7 +1,7 @@
github.com/AdguardTeam/dnsproxy v0.73.4 h1:FTIXX34wQqePjtWUD1I4QfWTq2B2N1gfOW/TzZDdR4o= github.com/AdguardTeam/dnsproxy v0.73.5 h1:3EiVaTfmuW6PcJGbqloR6ZdHACsrYkm9z0eH8ZQTZnQ=
github.com/AdguardTeam/dnsproxy v0.73.4/go.mod h1:18ssqhDgOCiVIwYmmVuXVM05wSwrzkO2yjKhVRWJX/g= github.com/AdguardTeam/dnsproxy v0.73.5/go.mod h1:Oqw+k7LyjDObfYzXYCkpgtirbzbUrmotr92jrb3N09I=
github.com/AdguardTeam/golibs v0.30.5 h1:xqat/N9o/V/AnakaWpqq+fGU/qJhKtL4A2pj66kC+TE= github.com/AdguardTeam/golibs v0.31.0 h1:Z0oPfLTLw6iZmpE58dePy2Bel0MaX+lnDwtFEE5EmIo=
github.com/AdguardTeam/golibs v0.30.5/go.mod h1:2wOvoAsubo/REnBiuu/YWYmkkzyFR52/QljMdQ2R58M= github.com/AdguardTeam/golibs v0.31.0/go.mod h1:wIkZ9o2UnppeW6/YD7yJB71dYbMhiuC1Fh/I2ElW7GQ=
github.com/AdguardTeam/urlfilter v0.20.0 h1:X32qiuVCVd8WDYCEsbdZKfXMzwdVqrdulamtUi4rmzs= github.com/AdguardTeam/urlfilter v0.20.0 h1:X32qiuVCVd8WDYCEsbdZKfXMzwdVqrdulamtUi4rmzs=
github.com/AdguardTeam/urlfilter v0.20.0/go.mod h1:gjrywLTxfJh6JOkwi9SU+frhP7kVVEZ5exFGkR99qpk= github.com/AdguardTeam/urlfilter v0.20.0/go.mod h1:gjrywLTxfJh6JOkwi9SU+frhP7kVVEZ5exFGkR99qpk=
github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I= github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I=
@@ -42,8 +42,8 @@ github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8= github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8=
github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo= github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo=
github.com/google/pprof v0.0.0-20241101162523-b92577c0c142 h1:sAGdeJj0bnMgUNVeUpp6AYlVdCt3/GdI3pGRqsNSQLs= github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad h1:a6HEuzUHeKH6hwfN/ZoQgRgVIWFJljSWa/zetS2WTvg=
github.com/google/pprof v0.0.0-20241101162523-b92577c0c142/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
github.com/google/renameio/v2 v2.0.0 h1:UifI23ZTGY8Tt29JbYFiuyIU3eX+RNFtUwefq9qAhxg= github.com/google/renameio/v2 v2.0.0 h1:UifI23ZTGY8Tt29JbYFiuyIU3eX+RNFtUwefq9qAhxg=
github.com/google/renameio/v2 v2.0.0/go.mod h1:BtmJXm5YlszgC+TD4HOEEUFgkJP3nLxehU6hfe7jRt4= github.com/google/renameio/v2 v2.0.0/go.mod h1:BtmJXm5YlszgC+TD4HOEEUFgkJP3nLxehU6hfe7jRt4=
github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
@@ -51,8 +51,8 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/hugelgupf/socketpair v0.0.0-20190730060125-05d35a94e714 h1:/jC7qQFrv8CrSJVmaolDVOxTfS9kc36uB6H40kdbQq8= github.com/hugelgupf/socketpair v0.0.0-20190730060125-05d35a94e714 h1:/jC7qQFrv8CrSJVmaolDVOxTfS9kc36uB6H40kdbQq8=
github.com/hugelgupf/socketpair v0.0.0-20190730060125-05d35a94e714/go.mod h1:2Goc3h8EklBH5mspfHFxBnEoURQCGzQQH1ga9Myjvis= github.com/hugelgupf/socketpair v0.0.0-20190730060125-05d35a94e714/go.mod h1:2Goc3h8EklBH5mspfHFxBnEoURQCGzQQH1ga9Myjvis=
github.com/insomniacslk/dhcp v0.0.0-20240829085014-a3a4c1f04475 h1:hxST5pwMBEOWmxpkX20w9oZG+hXdhKmAIPQ3NGGAxas= github.com/insomniacslk/dhcp v0.0.0-20241203100832-a481575ed0ef h1:NzQKDfd5ZOPnuZYf9MnRee8x2qecsVqzsnaLjEZiBko=
github.com/insomniacslk/dhcp v0.0.0-20240829085014-a3a4c1f04475/go.mod h1:KclMyHxX06VrVr0DJmeFSUb1ankt7xTfoOA35pCkoic= github.com/insomniacslk/dhcp v0.0.0-20241203100832-a481575ed0ef/go.mod h1:KclMyHxX06VrVr0DJmeFSUb1ankt7xTfoOA35pCkoic=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/josharian/native v1.0.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w= github.com/josharian/native v1.0.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
github.com/josharian/native v1.1.1-0.20230202152459-5c7d0dd6ab86 h1:elKwZS1OcdQ0WwEDBeqxKwb7WB62QX8bvZ/FJnVXIfk= github.com/josharian/native v1.1.1-0.20230202152459-5c7d0dd6ab86 h1:elKwZS1OcdQ0WwEDBeqxKwb7WB62QX8bvZ/FJnVXIfk=
@@ -80,10 +80,10 @@ github.com/miekg/dns v1.1.62 h1:cN8OuEF1/x5Rq6Np+h1epln8OiyPWV+lROx9LxcGgIQ=
github.com/miekg/dns v1.1.62/go.mod h1:mvDlcItzm+br7MToIKqkglaGhlFMHJ9DTNNWONWXbNQ= github.com/miekg/dns v1.1.62/go.mod h1:mvDlcItzm+br7MToIKqkglaGhlFMHJ9DTNNWONWXbNQ=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/onsi/ginkgo/v2 v2.21.0 h1:7rg/4f3rB88pb5obDgNZrNHrQ4e6WpjonchcpuBRnZM= github.com/onsi/ginkgo/v2 v2.22.1 h1:QW7tbJAUDyVDVOM5dFa7qaybo+CRfR7bemlQUN6Z8aM=
github.com/onsi/ginkgo/v2 v2.21.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo= github.com/onsi/ginkgo/v2 v2.22.1/go.mod h1:S6aTpoRsSq2cZOd+pssHAlKW/Q/jZt6cPrPlnj4a1xM=
github.com/onsi/gomega v1.34.2 h1:pNCwDkzrsv7MS9kpaQvVb1aVLahQXyJ/Tv5oAZMI3i8= github.com/onsi/gomega v1.36.1 h1:bJDPBO7ibjxcbHMgSCoo4Yj18UWbKDlLwX1x9sybDcw=
github.com/onsi/gomega v1.34.2/go.mod h1:v1xfxRgk0KIsG+QOdm7p8UosrOzPYRo60fd3B/1Dukc= github.com/onsi/gomega v1.36.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog=
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ= github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ=
@@ -126,10 +126,10 @@ go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU=
go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM= go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ= golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg= golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f h1:XdNn9LlyWAhLVp6P/i8QYBW+hlyhrhei9uErw2B5GJo= golang.org/x/exp v0.0.0-20241217172543-b2144cdd0a67 h1:1UoZQm6f0P/ZO0w1Ri+f+ifG/gXhegadRdwBIXEFWDo=
golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f/go.mod h1:D5SMRVC3C2/4+F/DB1wZsLRnSNimn2Sp/NPsCrsv8ak= golang.org/x/exp v0.0.0-20241217172543-b2144cdd0a67/go.mod h1:qj5a5QZpwLU2NLQudwIN5koi3beDhSAlJwa67PuM98c=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4= golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4=
@@ -140,12 +140,12 @@ golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo= golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM= golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ= golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190322080309-f49334f85ddc/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190322080309-f49334f85ddc/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -161,20 +161,20 @@ golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.27.0 h1:qEKojBykQkQ4EynWy4S8Weg69NumxKdn40Fce3uc/8o= golang.org/x/tools v0.28.0 h1:WuB6qZ4RPCQo5aP3WdKZS7i595EdWqWR8vqJTlwTVK8=
golang.org/x/tools v0.27.0/go.mod h1:sUi0ZgbwW9ZPAq26Ekut+weQPR5eIM6GQLQ1Yjm1H0Q= golang.org/x/tools v0.28.0/go.mod h1:dcIOrVd3mfQKTgrDVQHqCPMWy6lnhfhtX3hLXYVLfRw=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gonum.org/v1/gonum v0.15.1 h1:FNy7N6OUZVUaWG9pTiD+jlhdQ3lMP+/LcTpJ6+a8sQ0= gonum.org/v1/gonum v0.15.1 h1:FNy7N6OUZVUaWG9pTiD+jlhdQ3lMP+/LcTpJ6+a8sQ0=
gonum.org/v1/gonum v0.15.1/go.mod h1:eZTZuRFrzu5pcyjN5wJhcIhnUdNijYxX1T2IcrOGY0o= gonum.org/v1/gonum v0.15.1/go.mod h1:eZTZuRFrzu5pcyjN5wJhcIhnUdNijYxX1T2IcrOGY0o=
google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA=
google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

View File

@@ -521,7 +521,7 @@ func TestUpgradeSchema11to12(t *testing.T) {
name string name string
}{{ }{{
ivl: 1, ivl: 1,
want: timeutil.Duration{Duration: timeutil.Day}, want: timeutil.Duration(timeutil.Day),
wantErr: "", wantErr: "",
name: "success", name: "success",
}, { }, {
@@ -604,7 +604,7 @@ func TestUpgradeSchema11to12(t *testing.T) {
ivlVal, ok = ivl.(timeutil.Duration) ivlVal, ok = ivl.(timeutil.Duration)
require.True(t, ok) require.True(t, ok)
assert.Equal(t, 90*24*time.Hour, ivlVal.Duration) assert.Equal(t, 90*24*time.Hour, time.Duration(ivlVal))
}) })
} }
@@ -1055,12 +1055,12 @@ func TestUpgradeSchema19to20(t *testing.T) {
name string name string
}{{ }{{
ivl: 1, ivl: 1,
want: timeutil.Duration{Duration: timeutil.Day}, want: timeutil.Duration(timeutil.Day),
wantErr: "", wantErr: "",
name: "success", name: "success",
}, { }, {
ivl: 0, ivl: 0,
want: timeutil.Duration{Duration: timeutil.Day}, want: timeutil.Duration(timeutil.Day),
wantErr: "", wantErr: "",
name: "success", name: "success",
}, { }, {
@@ -1143,7 +1143,7 @@ func TestUpgradeSchema19to20(t *testing.T) {
ivlVal, ok = ivl.(timeutil.Duration) ivlVal, ok = ivl.(timeutil.Duration)
require.True(t, ok) require.True(t, ok)
assert.Equal(t, 24*time.Hour, ivlVal.Duration) assert.Equal(t, 24*time.Hour, time.Duration(ivlVal))
}) })
} }

View File

@@ -37,7 +37,7 @@ func migrateTo12(diskConf yobj) (err error) {
qlogIvl = 90 qlogIvl = 90
} }
dns[field] = timeutil.Duration{Duration: time.Duration(qlogIvl) * timeutil.Day} dns[field] = timeutil.Duration(time.Duration(qlogIvl) * timeutil.Day)
return nil return nil
} }

View File

@@ -38,7 +38,7 @@ func migrateTo20(diskConf yobj) (err error) {
ivl = 1 ivl = 1
} }
stats[field] = timeutil.Duration{Duration: time.Duration(ivl) * timeutil.Day} stats[field] = timeutil.Duration(time.Duration(ivl) * timeutil.Day)
return nil return nil
} }

View File

@@ -48,7 +48,7 @@ func migrateTo23(diskConf yobj) (err error) {
diskConf["http"] = yobj{ diskConf["http"] = yobj{
"address": netip.AddrPortFrom(bindHostAddr, uint16(bindPort)).String(), "address": netip.AddrPortFrom(bindHostAddr, uint16(bindPort)).String(),
"session_ttl": timeutil.Duration{Duration: time.Duration(sessionTTL) * time.Hour}.String(), "session_ttl": timeutil.Duration(time.Duration(sessionTTL) * time.Hour).String(),
} }
delete(diskConf, "bind_host") delete(diskConf, "bind_host")

View File

@@ -1,61 +1,50 @@
# Testing DHCP Server # Testing DHCP Server
Contents: Contents:
* [Test setup with Virtual Box](#vbox)
* [Quick test with DHCPTest](#dhcptest)
## <a href="#vbox" id="vbox" name="vbox">Test setup with Virtual Box</a> - [Test setup with Virtual Box](#vbox)
- [Quick test with DHCPTest](#dhcptest)
### Prerequisites ## <a href="#vbox" id="vbox" name="vbox">Test setup with Virtual Box</a>
### Prerequisites
To set up a test environment for DHCP server you will need: To set up a test environment for DHCP server you will need:
* Linux AG Home host machine (Virtual). - Linux AG Home host machine (Virtual)
* Virtual Box. - Virtual Box
* Virtual machine (guest OS doesn't matter). - Virtual machine (guest OS doesn't matter)
### Configure Virtual Box ### Configure Virtual Box
1. Install Virtual Box and run the following command to create a Host-Only 1. Install Virtual Box and run the following command to create a Host-Only network:
network:
```sh ```sh
$ VBoxManage hostonlyif create VBoxManage hostonlyif create
``` ```
You can check its status by `ip a` command. You can check its status by `ip a` command.
You can also set up Host-Only network using Virtual Box menu: You can also set up Host-Only network using Virtual Box menu in *File → Host Network Manager.*
``` 2. Create your virtual machine and set up its network in *VM Settings → Network → Host-only Adapter.*
File -> Host Network Manager...
```
2. Create your virtual machine and set up its network: 3. Start your VM, install an OS. Configure your network interface to use DHCP and the OS should ask for a IP address from our DHCP server.
``` 4. To see the current IP addresses on client OS you can use `ip a` command on Linux or `ipconfig` on Windows.
VM Settings -> Network -> Host-only Adapter
```
3. Start your VM, install an OS. Configure your network interface to use 5. To force the client OS to request an IP from DHCP server again, you can use `dhclient` on Linux or `ipconfig /release` on Windows.
DHCP and the OS should ask for a IP address from our DHCP server.
4. To see the current IP addresses on client OS you can use `ip a` command on ### Configure server
Linux or `ipconfig` on Windows.
5. To force the client OS to request an IP from DHCP server again, you can 1. Edit server configuration file `AdGuardHome.yaml`, for example:
use `dhclient` on Linux or `ipconfig /release` on Windows.
### Configure server ```yaml
dhcp:
1. Edit server configuration file `AdGuardHome.yaml`, for example: enabled: true
interface_name: vboxnet0
```yaml local_domain_name: lan
dhcp: dhcpv4:
enabled: true
interface_name: vboxnet0
local_domain_name: lan
dhcpv4:
gateway_ip: 192.168.56.1 gateway_ip: 192.168.56.1
subnet_mask: 255.255.255.0 subnet_mask: 255.255.255.0
range_start: 192.168.56.2 range_start: 192.168.56.2
@@ -63,34 +52,33 @@ To set up a test environment for DHCP server you will need:
lease_duration: 86400 lease_duration: 86400
icmp_timeout_msec: 1000 icmp_timeout_msec: 1000
options: [] options: []
dhcpv6: dhcpv6:
range_start: 2001::1 range_start: 2001::1
lease_duration: 86400 lease_duration: 86400
ra_slaac_only: false ra_slaac_only: false
ra_allow_slaac: false ra_allow_slaac: false
``` ```
2. Start the server 2. Start the server:
```sh ```sh
./AdGuardHome -v ./AdGuardHome -v
``` ```
There should be a message in log which shows that DHCP server is ready: There should be a message in log which shows that DHCP server is ready:
``` ```none
[info] DHCP: listening on 0.0.0.0:67 [info] dhcpv4: listening
``` ```
## <a href="#dhcptest" id="dhcptest" name="dhcptest">Quick test with DHCPTest utility</a> ## <a href="#dhcptest" id="dhcptest" name="dhcptest">Quick test with DHCPTest utility</a>
### Prerequisites ### Prerequisites
* [DHCP test utility][dhcptest-gh]. - [DHCP test utility][dhcptest-gh].
### Quick test ### Quick test
The DHCP server could be tested for DISCOVER-OFFER packets with in The DHCP server could be tested for DISCOVER-OFFER packets with in interactive mode.
interactive mode.
[dhcptest-gh]: https://github.com/CyberShadow/dhcptest [dhcptest-gh]: https://github.com/CyberShadow/dhcptest

View File

@@ -84,7 +84,7 @@ func parseDHCPOptionDur(s string) (val dhcpv4.OptionValue, err error) {
return nil, fmt.Errorf("decoding dur: %w", err) return nil, fmt.Errorf("decoding dur: %w", err)
} }
return dhcpv4.Duration(v.Duration), nil return dhcpv4.Duration(v), nil
} }
// parseDHCPOptionUint parses a DHCP option as an unsigned integer. bitSize is // parseDHCPOptionUint parses a DHCP option as an unsigned integer. bitSize is

View File

@@ -144,8 +144,8 @@ func TestParseOpt(t *testing.T) {
in: "24 dur 3y", in: "24 dur 3y",
wantCode: nil, wantCode: nil,
wantVal: nil, wantVal: nil,
wantErrMsg: "invalid option string \"24 dur 3y\": decoding dur: " + wantErrMsg: `invalid option string "24 dur 3y": decoding dur: time: ` +
"unmarshaling duration: time: unknown unit \"y\" in duration \"3y\"", `unknown unit "y" in duration "3y"`,
}, { }, {
name: "u8_error", name: "u8_error",
in: "23 u8 256", in: "23 u8 256",

View File

@@ -81,7 +81,7 @@ func (s *Server) clientIDFromDNSContext(pctx *proxy.DNSContext) (clientID string
cliSrvName, err := clientServerName(pctx, proto) cliSrvName, err := clientServerName(pctx, proto)
if err != nil { if err != nil {
return "", err return "", fmt.Errorf("getting client server-name: %w", err)
} }
clientID, err = clientIDFromClientServerName( clientID, err = clientIDFromClientServerName(

View File

@@ -3,6 +3,7 @@ package dnsforward
import ( import (
"crypto/tls" "crypto/tls"
"fmt" "fmt"
"net/http"
"path" "path"
"strings" "strings"
@@ -118,17 +119,13 @@ func clientServerName(pctx *proxy.DNSContext, proto proxy.Proto) (srvName string
switch proto { switch proto {
case proxy.ProtoHTTPS: case proxy.ProtoHTTPS:
r := pctx.HTTPRequest var fromHost bool
if connState := r.TLS; connState != nil { srvName, fromHost, err = clientServerNameFromHTTP(pctx.HTTPRequest)
srvName = connState.ServerName if err != nil {
} else if r.Host != "" { return "", fmt.Errorf("from http: %w", err)
var host string }
host, err = netutil.SplitHost(r.Host)
if err != nil {
return "", fmt.Errorf("parsing host: %w", err)
}
srvName = host if fromHost {
from = "host header" from = "host header"
} }
case proxy.ProtoQUIC: case proxy.ProtoQUIC:
@@ -153,3 +150,23 @@ func clientServerName(pctx *proxy.DNSContext, proto proxy.Proto) (srvName string
return srvName, nil return srvName, nil
} }
// clientServerNameFromHTTP returns the TLS server name or the value of the host
// header depending on the protocol. fromHost is true if srvName comes from the
// "Host" HTTP header.
func clientServerNameFromHTTP(r *http.Request) (srvName string, fromHost bool, err error) {
if connState := r.TLS; connState != nil {
return connState.ServerName, false, nil
}
if r.Host == "" {
return "", false, nil
}
srvName, err = netutil.SplitHost(r.Host)
if err != nil {
return "", false, fmt.Errorf("parsing host: %w", err)
}
return srvName, true, nil
}

View File

@@ -348,7 +348,7 @@ func (s *Server) newProxyConfig() (conf *proxy.Config, err error) {
conf.EDNSAddr = net.IP(srvConf.EDNSClientSubnet.CustomIP.AsSlice()) conf.EDNSAddr = net.IP(srvConf.EDNSClientSubnet.CustomIP.AsSlice())
} }
err = setProxyUpstreamMode(conf, srvConf.UpstreamMode, srvConf.FastestTimeout.Duration) err = setProxyUpstreamMode(conf, srvConf.UpstreamMode, time.Duration(srvConf.FastestTimeout))
if err != nil { if err != nil {
return nil, fmt.Errorf("upstream mode: %w", err) return nil, fmt.Errorf("upstream mode: %w", err)
} }

View File

@@ -740,7 +740,7 @@ func (s *Server) prepareInternalProxy() (err error) {
MessageConstructor: s, MessageConstructor: s,
} }
err = setProxyUpstreamMode(conf, srvConf.UpstreamMode, srvConf.FastestTimeout.Duration) err = setProxyUpstreamMode(conf, srvConf.UpstreamMode, time.Duration(srvConf.FastestTimeout))
if err != nil { if err != nil {
return fmt.Errorf("invalid upstream mode: %w", err) return fmt.Errorf("invalid upstream mode: %w", err)
} }

View File

@@ -1,70 +0,0 @@
# AdGuard Home's DNS filtering go library
Example use:
```bash
[ -z "$GOPATH" ] && export GOPATH=$HOME/go
go get -d github.com/AdguardTeam/AdGuardHome/filtering
```
Create file filter.go
```filter.go
package main
import (
"github.com/AdguardTeam/AdGuardHome/filtering"
"log"
)
func main() {
filter := filtering.New()
filter.AddRule("||dou*ck.net^")
host := "www.doubleclick.net"
res, err := filter.CheckHost(host)
if err != nil {
// temporary failure
log.Fatalf("Failed to check host %q: %s", host, err)
}
if res.IsFiltered {
log.Printf("Host %s is filtered, reason - %q, matched rule: %q", host, res.Reason, res.Rule)
} else {
log.Printf("Host %s is not filtered, reason - %q", host, res.Reason)
}
}
```
And then run it:
```bash
go run filter.go
```
You will get:
```
2000/01/01 00:00:00 Host www.doubleclick.net is filtered, reason - 'FilteredBlackList', matched rule: '||dou*ck.net^'
```
You can also enable checking against AdGuard's SafeBrowsing:
```go
package main
import (
"github.com/AdguardTeam/AdGuardHome/filtering"
"log"
)
func main() {
filter := filtering.New()
filter.EnableSafeBrowsing()
host := "wmconvirus.narod.ru" // hostname for testing safebrowsing
res, err := filter.CheckHost(host)
if err != nil {
// temporary failure
log.Fatalf("Failed to check host %q: %s", host, err)
}
if res.IsFiltered {
log.Printf("Host %s is filtered, reason - %q, matched rule: %q", host, res.Reason, res.Rule)
} else {
log.Printf("Host %s is not filtered, reason - %q", host, res.Reason)
}
}
```

View File

@@ -18,7 +18,6 @@ func TestFilter_Refresh(t *testing.T) {
t.Parallel() t.Parallel()
cacheDir := t.TempDir() cacheDir := t.TempDir()
uid := rulelist.MustNewUID()
const fltData = testRuleTextTitle + testRuleTextBlocked const fltData = testRuleTextTitle + testRuleTextBlocked
fileURL, srvURL := newFilterLocations(t, cacheDir, fltData, fltData) fileURL, srvURL := newFilterLocations(t, cacheDir, fltData, fltData)
@@ -54,6 +53,7 @@ func TestFilter_Refresh(t *testing.T) {
t.Run(tc.name, func(t *testing.T) { t.Run(tc.name, func(t *testing.T) {
t.Parallel() t.Parallel()
uid := rulelist.MustNewUID()
f, err := rulelist.NewFilter(&rulelist.FilterConfig{ f, err := rulelist.NewFilter(&rulelist.FilterConfig{
URL: tc.url, URL: tc.url,
Name: tc.name, Name: tc.name,

View File

@@ -400,7 +400,7 @@ func (clients *clientsContainer) UpstreamConfigByID(
upstreams, upstreams,
&upstream.Options{ &upstream.Options{
Bootstrap: bootstrap, Bootstrap: bootstrap,
Timeout: config.DNS.UpstreamTimeout.Duration, Timeout: time.Duration(config.DNS.UpstreamTimeout),
HTTPVersions: dnsforward.UpstreamHTTPVersions(config.DNS.UseHTTP3Upstreams), HTTPVersions: dnsforward.UpstreamHTTPVersions(config.DNS.UseHTTP3Upstreams),
PreferIPv6: config.DNS.BootstrapPreferIPv6, PreferIPv6: config.DNS.BootstrapPreferIPv6,
}, },

View File

@@ -424,6 +424,8 @@ func (clients *clientsContainer) handleUpdateClient(w http.ResponseWriter, r *ht
} }
// handleFindClient is the handler for GET /control/clients/find HTTP API. // handleFindClient is the handler for GET /control/clients/find HTTP API.
//
// Deprecated: Remove it when migration to the new API is over.
func (clients *clientsContainer) handleFindClient(w http.ResponseWriter, r *http.Request) { func (clients *clientsContainer) handleFindClient(w http.ResponseWriter, r *http.Request) {
q := r.URL.Query() q := r.URL.Query()
data := []map[string]*clientJSON{} data := []map[string]*clientJSON{}
@@ -433,19 +435,58 @@ func (clients *clientsContainer) handleFindClient(w http.ResponseWriter, r *http
break break
} }
ip, _ := netip.ParseAddr(idStr)
c, ok := clients.storage.Find(idStr)
var cj *clientJSON
if !ok {
cj = clients.findRuntime(ip, idStr)
} else {
cj = clientToJSON(c)
disallowed, rule := clients.clientChecker.IsBlockedClient(ip, idStr)
cj.Disallowed, cj.DisallowedRule = &disallowed, &rule
}
data = append(data, map[string]*clientJSON{ data = append(data, map[string]*clientJSON{
idStr: cj, idStr: clients.findClient(idStr),
})
}
aghhttp.WriteJSONResponseOK(w, r, data)
}
// findClient returns available information about a client by idStr from the
// client's storage or access settings. cj is guaranteed to be non-nil.
func (clients *clientsContainer) findClient(idStr string) (cj *clientJSON) {
ip, _ := netip.ParseAddr(idStr)
c, ok := clients.storage.Find(idStr)
if !ok {
return clients.findRuntime(ip, idStr)
}
cj = clientToJSON(c)
disallowed, rule := clients.clientChecker.IsBlockedClient(ip, idStr)
cj.Disallowed, cj.DisallowedRule = &disallowed, &rule
return cj
}
// searchQueryJSON is a request to the POST /control/clients/search HTTP API.
//
// TODO(s.chzhen): Add UIDs.
type searchQueryJSON struct {
Clients []searchClientJSON `json:"clients"`
}
// searchClientJSON is a part of [searchQueryJSON] that contains a string
// representation of the client's IP address, CIDR, MAC address, or ClientID.
type searchClientJSON struct {
ID string `json:"id"`
}
// handleSearchClient is the handler for the POST /control/clients/search HTTP API.
func (clients *clientsContainer) handleSearchClient(w http.ResponseWriter, r *http.Request) {
q := searchQueryJSON{}
err := json.NewDecoder(r.Body).Decode(&q)
if err != nil {
aghhttp.Error(r, w, http.StatusBadRequest, "failed to process request body: %s", err)
return
}
data := []map[string]*clientJSON{}
for _, c := range q.Clients {
idStr := c.ID
data = append(data, map[string]*clientJSON{
idStr: clients.findClient(idStr),
}) })
} }
@@ -493,5 +534,8 @@ func (clients *clientsContainer) registerWebHandlers() {
httpRegister(http.MethodPost, "/control/clients/add", clients.handleAddClient) httpRegister(http.MethodPost, "/control/clients/add", clients.handleAddClient)
httpRegister(http.MethodPost, "/control/clients/delete", clients.handleDelClient) httpRegister(http.MethodPost, "/control/clients/delete", clients.handleDelClient)
httpRegister(http.MethodPost, "/control/clients/update", clients.handleUpdateClient) httpRegister(http.MethodPost, "/control/clients/update", clients.handleUpdateClient)
httpRegister(http.MethodPost, "/control/clients/search", clients.handleSearchClient)
// Deprecated handler.
httpRegister(http.MethodGet, "/control/clients/find", clients.handleFindClient) httpRegister(http.MethodGet, "/control/clients/find", clients.handleFindClient)
} }

View File

@@ -16,6 +16,7 @@ import (
"github.com/AdguardTeam/AdGuardHome/internal/client" "github.com/AdguardTeam/AdGuardHome/internal/client"
"github.com/AdguardTeam/AdGuardHome/internal/filtering" "github.com/AdguardTeam/AdGuardHome/internal/filtering"
"github.com/AdguardTeam/AdGuardHome/internal/schedule" "github.com/AdguardTeam/AdGuardHome/internal/schedule"
"github.com/AdguardTeam/AdGuardHome/internal/whois"
"github.com/AdguardTeam/golibs/testutil" "github.com/AdguardTeam/golibs/testutil"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
@@ -408,3 +409,145 @@ func TestClientsContainer_HandleFindClient(t *testing.T) {
}) })
} }
} }
func TestClientsContainer_HandleSearchClient(t *testing.T) {
var (
runtimeCli = "runtime_client1"
runtimeCliIP = "3.3.3.3"
blockedCliIP = "4.4.4.4"
nonExistentCliIP = "5.5.5.5"
allowed = false
dissallowed = true
emptyRule = ""
disallowedRule = "disallowed_rule"
)
clients := newClientsContainer(t)
clients.clientChecker = &testBlockedClientChecker{
onIsBlockedClient: func(ip netip.Addr, _ string) (ok bool, rule string) {
if ip == netip.MustParseAddr(blockedCliIP) {
return true, disallowedRule
}
return false, emptyRule
},
}
ctx := testutil.ContextWithTimeout(t, testTimeout)
clientOne := newPersistentClientWithIDs(t, "client1", []string{testClientIP1})
err := clients.storage.Add(ctx, clientOne)
require.NoError(t, err)
clientTwo := newPersistentClientWithIDs(t, "client2", []string{testClientIP2})
err = clients.storage.Add(ctx, clientTwo)
require.NoError(t, err)
assertPersistentClients(t, clients, []*client.Persistent{clientOne, clientTwo})
clients.UpdateAddress(ctx, netip.MustParseAddr(runtimeCliIP), runtimeCli, nil)
testCases := []struct {
name string
query *searchQueryJSON
wantPersistent []*client.Persistent
wantRuntime *clientJSON
}{{
name: "single",
query: &searchQueryJSON{
Clients: []searchClientJSON{{
ID: testClientIP1,
}},
},
wantPersistent: []*client.Persistent{clientOne},
}, {
name: "multiple",
query: &searchQueryJSON{
Clients: []searchClientJSON{{
ID: testClientIP1,
}, {
ID: testClientIP2,
}},
},
wantPersistent: []*client.Persistent{clientOne, clientTwo},
}, {
name: "runtime",
query: &searchQueryJSON{
Clients: []searchClientJSON{{
ID: runtimeCliIP,
}},
},
wantRuntime: &clientJSON{
Name: runtimeCli,
IDs: []string{runtimeCliIP},
Disallowed: &allowed,
DisallowedRule: &emptyRule,
WHOIS: &whois.Info{},
},
}, {
name: "blocked_access",
query: &searchQueryJSON{
Clients: []searchClientJSON{{
ID: blockedCliIP,
}},
},
wantRuntime: &clientJSON{
IDs: []string{blockedCliIP},
Disallowed: &dissallowed,
DisallowedRule: &disallowedRule,
WHOIS: &whois.Info{},
},
}, {
name: "non_existing_client",
query: &searchQueryJSON{
Clients: []searchClientJSON{{
ID: nonExistentCliIP,
}},
},
wantRuntime: &clientJSON{
IDs: []string{nonExistentCliIP},
Disallowed: &allowed,
DisallowedRule: &emptyRule,
WHOIS: &whois.Info{},
},
}}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
var body []byte
body, err = json.Marshal(tc.query)
require.NoError(t, err)
var r *http.Request
r, err = http.NewRequest(http.MethodPost, "", bytes.NewReader(body))
require.NoError(t, err)
rw := httptest.NewRecorder()
clients.handleSearchClient(rw, r)
require.NoError(t, err)
require.Equal(t, http.StatusOK, rw.Code)
body, err = io.ReadAll(rw.Body)
require.NoError(t, err)
clientData := []map[string]*clientJSON{}
err = json.Unmarshal(body, &clientData)
require.NoError(t, err)
if tc.wantPersistent != nil {
assertPersistentClientsData(t, clients, clientData, tc.wantPersistent)
return
}
require.Len(t, clientData, 1)
require.Len(t, clientData[0], 1)
rc := clientData[0][tc.wantRuntime.IDs[0]]
assert.Equal(t, tc.wantRuntime, rc)
})
}
}

View File

@@ -339,7 +339,7 @@ var config = &configuration{
AuthBlockMin: 15, AuthBlockMin: 15,
HTTPConfig: httpConfig{ HTTPConfig: httpConfig{
Address: netip.AddrPortFrom(netip.IPv4Unspecified(), 3000), Address: netip.AddrPortFrom(netip.IPv4Unspecified(), 3000),
SessionTTL: timeutil.Duration{Duration: 30 * timeutil.Day}, SessionTTL: timeutil.Duration(30 * timeutil.Day),
Pprof: &httpPprofConfig{ Pprof: &httpPprofConfig{
Enabled: false, Enabled: false,
Port: 6060, Port: 6060,
@@ -355,9 +355,7 @@ var config = &configuration{
RefuseAny: true, RefuseAny: true,
UpstreamMode: dnsforward.UpstreamModeLoadBalance, UpstreamMode: dnsforward.UpstreamModeLoadBalance,
HandleDDR: true, HandleDDR: true,
FastestTimeout: timeutil.Duration{ FastestTimeout: timeutil.Duration(fastip.DefaultPingWaitTimeout),
Duration: fastip.DefaultPingWaitTimeout,
},
TrustedProxies: []netutil.Prefix{{ TrustedProxies: []netutil.Prefix{{
Prefix: netip.MustParsePrefix("127.0.0.0/8"), Prefix: netip.MustParsePrefix("127.0.0.0/8"),
@@ -378,7 +376,7 @@ var config = &configuration{
// was later increased to 300 due to https://github.com/AdguardTeam/AdGuardHome/issues/2257 // was later increased to 300 due to https://github.com/AdguardTeam/AdGuardHome/issues/2257
MaxGoroutines: 300, MaxGoroutines: 300,
}, },
UpstreamTimeout: timeutil.Duration{Duration: dnsforward.DefaultTimeout}, UpstreamTimeout: timeutil.Duration(dnsforward.DefaultTimeout),
UsePrivateRDNS: true, UsePrivateRDNS: true,
ServePlainDNS: true, ServePlainDNS: true,
HostsFileEnabled: true, HostsFileEnabled: true,
@@ -391,13 +389,13 @@ var config = &configuration{
QueryLog: queryLogConfig{ QueryLog: queryLogConfig{
Enabled: true, Enabled: true,
FileEnabled: true, FileEnabled: true,
Interval: timeutil.Duration{Duration: 90 * timeutil.Day}, Interval: timeutil.Duration(90 * timeutil.Day),
MemSize: 1000, MemSize: 1000,
Ignored: []string{}, Ignored: []string{},
}, },
Stats: statsConfig{ Stats: statsConfig{
Enabled: true, Enabled: true,
Interval: timeutil.Duration{Duration: 1 * timeutil.Day}, Interval: timeutil.Duration(1 * timeutil.Day),
Ignored: []string{}, Ignored: []string{},
}, },
// NOTE: Keep these parameters in sync with the one put into // NOTE: Keep these parameters in sync with the one put into
@@ -565,8 +563,8 @@ func parseConfig() (err error) {
return err return err
} }
if config.DNS.UpstreamTimeout.Duration == 0 { if config.DNS.UpstreamTimeout == 0 {
config.DNS.UpstreamTimeout = timeutil.Duration{Duration: dnsforward.DefaultTimeout} config.DNS.UpstreamTimeout = timeutil.Duration(dnsforward.DefaultTimeout)
} }
// Do not wrap the error because it's informative enough as is. // Do not wrap the error because it's informative enough as is.
@@ -659,7 +657,7 @@ func (c *configuration) write() (err error) {
if Context.stats != nil { if Context.stats != nil {
statsConf := stats.Config{} statsConf := stats.Config{}
Context.stats.WriteDiskConfig(&statsConf) Context.stats.WriteDiskConfig(&statsConf)
config.Stats.Interval = timeutil.Duration{Duration: statsConf.Limit} config.Stats.Interval = timeutil.Duration(statsConf.Limit)
config.Stats.Enabled = statsConf.Enabled config.Stats.Enabled = statsConf.Enabled
config.Stats.Ignored = statsConf.Ignored.Values() config.Stats.Ignored = statsConf.Ignored.Values()
} }
@@ -670,7 +668,7 @@ func (c *configuration) write() (err error) {
config.DNS.AnonymizeClientIP = dc.AnonymizeClientIP config.DNS.AnonymizeClientIP = dc.AnonymizeClientIP
config.QueryLog.Enabled = dc.Enabled config.QueryLog.Enabled = dc.Enabled
config.QueryLog.FileEnabled = dc.FileEnabled config.QueryLog.FileEnabled = dc.FileEnabled
config.QueryLog.Interval = timeutil.Duration{Duration: dc.RotationIvl} config.QueryLog.Interval = timeutil.Duration(dc.RotationIvl)
config.QueryLog.MemSize = dc.MemSize config.QueryLog.MemSize = dc.MemSize
config.QueryLog.Ignored = dc.Ignored.Values() config.QueryLog.Ignored = dc.Ignored.Values()
} }

View File

@@ -54,7 +54,7 @@ func initDNS(baseLogger *slog.Logger, statsDir, querylogDir string) (err error)
statsConf := stats.Config{ statsConf := stats.Config{
Logger: baseLogger.With(slogutil.KeyPrefix, "stats"), Logger: baseLogger.With(slogutil.KeyPrefix, "stats"),
Filename: filepath.Join(statsDir, "stats.db"), Filename: filepath.Join(statsDir, "stats.db"),
Limit: config.Stats.Interval.Duration, Limit: time.Duration(config.Stats.Interval),
ConfigModified: onConfigModified, ConfigModified: onConfigModified,
HTTPRegister: httpRegister, HTTPRegister: httpRegister,
Enabled: config.Stats.Enabled, Enabled: config.Stats.Enabled,
@@ -80,7 +80,7 @@ func initDNS(baseLogger *slog.Logger, statsDir, querylogDir string) (err error)
FindClient: Context.clients.findMultiple, FindClient: Context.clients.findMultiple,
BaseDir: querylogDir, BaseDir: querylogDir,
AnonymizeClientIP: config.DNS.AnonymizeClientIP, AnonymizeClientIP: config.DNS.AnonymizeClientIP,
RotationIvl: config.QueryLog.Interval.Duration, RotationIvl: time.Duration(config.QueryLog.Interval),
MemSize: config.QueryLog.MemSize, MemSize: config.QueryLog.MemSize,
Enabled: config.QueryLog.Enabled, Enabled: config.QueryLog.Enabled,
FileEnabled: config.QueryLog.FileEnabled, FileEnabled: config.QueryLog.FileEnabled,
@@ -243,7 +243,7 @@ func newServerConfig(
Config: fwdConf, Config: fwdConf,
TLSConfig: newDNSTLSConfig(tlsConf, hosts), TLSConfig: newDNSTLSConfig(tlsConf, hosts),
TLSAllowUnencryptedDoH: tlsConf.AllowUnencryptedDoH, TLSAllowUnencryptedDoH: tlsConf.AllowUnencryptedDoH,
UpstreamTimeout: dnsConf.UpstreamTimeout.Duration, UpstreamTimeout: time.Duration(dnsConf.UpstreamTimeout),
TLSv12Roots: Context.tlsRoots, TLSv12Roots: Context.tlsRoots,
ConfigModified: onConfigModified, ConfigModified: onConfigModified,
HTTPRegister: httpReg, HTTPRegister: httpReg,

View File

@@ -787,7 +787,7 @@ func initUsers() (auth *Auth, err error) {
trustedProxies := netutil.SliceSubnetSet(netutil.UnembedPrefixes(config.DNS.TrustedProxies)) trustedProxies := netutil.SliceSubnetSet(netutil.UnembedPrefixes(config.DNS.TrustedProxies))
sessionTTL := config.HTTPConfig.SessionTTL.Seconds() sessionTTL := time.Duration(config.HTTPConfig.SessionTTL).Seconds()
auth = InitAuth(sessFilename, config.Users, uint32(sessionTTL), rateLimiter, trustedProxies) auth = InitAuth(sessFilename, config.Users, uint32(sessionTTL), rateLimiter, trustedProxies)
if auth == nil { if auth == nil {
return nil, errors.Error("initializing auth module failed") return nil, errors.Error("initializing auth module failed")

View File

@@ -13,6 +13,7 @@ import (
type ServiceWithConfig[ConfigType any] interface { type ServiceWithConfig[ConfigType any] interface {
service.Interface service.Interface
// Config returns a deep clone of the configuration of the service.
Config() (c ConfigType) Config() (c ConfigType)
} }

View File

@@ -1,15 +1,17 @@
# AdGuard Home v0.108.0 Changelog DRAFT # AdGuard Home v0.108.0 Changelog DRAFT
This changelog should be merged into the main one once the next API matures This changelog should be merged into the main one once the next API matures enough.
enough.
## [v0.108.0] - TODO ## [v0.108.0] - TODO
### Added ### Added
- The ability to change the port of the pprof debug API. - The ability to change the port of the pprof debug API.
- The ability to log to stderr using `--logFile=stderr`. - The ability to log to stderr using `--logFile=stderr`.
- The new `--web-addr` flag to set the Web UI address in a `host:port` form. - The new `--web-addr` flag to set the Web UI address in a `host:port` form.
- `SIGHUP` now reloads all configuration from the configuration file ([#5676]). - `SIGHUP` now reloads all configuration from the configuration file ([#5676]).
### Changed ### Changed
@@ -20,20 +22,21 @@ enough.
#### Other changes #### Other changes
- `-h` is now an alias for `--help` instead of the removed `--host`, see below. - `-h` is now an alias for `--help` instead of the removed `--host`, see below. Use `--web-addr=host:port` to set an address on which to serve the Web UI.
Use `--web-addr=host:port` to set an address on which to serve the Web UI.
### Fixed ### Fixed
- `--check-config` breaking the configuration file ([#4067]). - `--check-config` breaking the configuration file ([#4067]).
- Inconsistent application of `--work-dir/-w` ([#2598], [#2902]). - Inconsistent application of `--work-dir/-w` ([#2598], [#2902]).
- The order of `-v/--verbose` and `--version` being significant ([#2893]). - The order of `-v/--verbose` and `--version` being significant ([#2893]).
### Removed ### Removed
- The deprecated `--no-mem-optimization` and `--no-etc-hosts` flags. - The deprecated `--no-mem-optimization` and `--no-etc-hosts` flags.
- `--host` and `-p/--port` flags. Use `--web-addr=host:port` to set an address
on which to serve the Web UI. `-h` is now an alias for `--help`, see above. - `--host` and `-p/--port` flags. Use `--web-addr=host:port` to set an address on which to serve the Web UI. `-h` is now an alias for `--help`, see above.
[#2598]: https://github.com/AdguardTeam/AdGuardHome/issues/2598 [#2598]: https://github.com/AdguardTeam/AdGuardHome/issues/2598
[#2893]: https://github.com/AdguardTeam/AdGuardHome/issues/2893 [#2893]: https://github.com/AdguardTeam/AdGuardHome/issues/2893

View File

@@ -1,12 +1,12 @@
package configmgr package configmgr
import ( import (
"fmt"
"net/netip" "net/netip"
"github.com/AdguardTeam/golibs/container" "github.com/AdguardTeam/golibs/container"
"github.com/AdguardTeam/golibs/errors" "github.com/AdguardTeam/golibs/errors"
"github.com/AdguardTeam/golibs/timeutil" "github.com/AdguardTeam/golibs/timeutil"
"github.com/AdguardTeam/golibs/validate"
) )
// config is the top-level on-disk configuration structure. // config is the top-level on-disk configuration structure.
@@ -19,10 +19,10 @@ type config struct {
} }
// type check // type check
var _ validator = (*config)(nil) var _ validate.Interface = (*config)(nil)
// validate implements the [validator] interface for *config. // Validate implements the [validate.Interface] interface for *config.
func (c *config) validate() (err error) { func (c *config) Validate() (err error) {
if c == nil { if c == nil {
return errors.ErrNoValue return errors.ErrNoValue
} }
@@ -30,7 +30,7 @@ func (c *config) validate() (err error) {
// TODO(a.garipov): Add more validations. // TODO(a.garipov): Add more validations.
// Keep this in the same order as the fields in the config. // Keep this in the same order as the fields in the config.
validators := container.KeyValues[string, validator]{{ validators := container.KeyValues[string, validate.Interface]{{
Key: "dns", Key: "dns",
Value: c.DNS, Value: c.DNS,
}, { }, {
@@ -41,14 +41,12 @@ func (c *config) validate() (err error) {
Value: c.Log, Value: c.Log,
}} }}
var errs []error
for _, kv := range validators { for _, kv := range validators {
err = kv.Value.validate() errs = validate.Append(errs, kv.Key, kv.Value)
if err != nil {
return fmt.Errorf("%s: %w", kv.Key, err)
}
} }
return nil return errors.Join(errs...)
} }
// dnsConfig is the on-disk DNS configuration. // dnsConfig is the on-disk DNS configuration.
@@ -63,21 +61,19 @@ type dnsConfig struct {
} }
// type check // type check
var _ validator = (*dnsConfig)(nil) var _ validate.Interface = (*dnsConfig)(nil)
// validate implements the [validator] interface for *dnsConfig. // Validate implements the [validate.Interface] interface for *dnsConfig.
// //
// TODO(a.garipov): Add more validations. // TODO(a.garipov): Add more validations.
func (c *dnsConfig) validate() (err error) { func (c *dnsConfig) Validate() (err error) {
// TODO(a.garipov): Add more validations. if c == nil {
switch {
case c == nil:
return errors.ErrNoValue return errors.ErrNoValue
case c.UpstreamTimeout.Duration <= 0:
return newErrNotPositive("upstream_timeout", c.UpstreamTimeout)
default:
return nil
} }
// TODO(a.garipov): Add more validations.
return validate.Positive("upstream_timeout", c.UpstreamTimeout)
} }
// httpConfig is the on-disk web API configuration. // httpConfig is the on-disk web API configuration.
@@ -92,20 +88,23 @@ type httpConfig struct {
} }
// type check // type check
var _ validator = (*httpConfig)(nil) var _ validate.Interface = (*httpConfig)(nil)
// validate implements the [validator] interface for *httpConfig. // Validate implements the [validate.Interface] interface for *httpConfig.
// //
// TODO(a.garipov): Add more validations. // TODO(a.garipov): Add more validations.
func (c *httpConfig) validate() (err error) { func (c *httpConfig) Validate() (err error) {
switch { if c == nil {
case c == nil:
return errors.ErrNoValue return errors.ErrNoValue
case c.Timeout.Duration <= 0:
return newErrNotPositive("timeout", c.Timeout)
default:
return c.Pprof.validate()
} }
errs := []error{
validate.Positive("timeout", c.Timeout),
}
errs = validate.Append(errs, "pprof", c.Pprof)
return errors.Join(errs...)
} }
// httpPprofConfig is the on-disk pprof configuration. // httpPprofConfig is the on-disk pprof configuration.
@@ -115,10 +114,10 @@ type httpPprofConfig struct {
} }
// type check // type check
var _ validator = (*httpPprofConfig)(nil) var _ validate.Interface = (*httpPprofConfig)(nil)
// validate implements the [validator] interface for *httpPprofConfig. // Validate implements the [validate.Interface] interface for *httpPprofConfig.
func (c *httpPprofConfig) validate() (err error) { func (c *httpPprofConfig) Validate() (err error) {
if c == nil { if c == nil {
return errors.ErrNoValue return errors.ErrNoValue
} }
@@ -128,17 +127,17 @@ func (c *httpPprofConfig) validate() (err error) {
// logConfig is the on-disk web API configuration. // logConfig is the on-disk web API configuration.
type logConfig struct { type logConfig struct {
// TODO(a.garipov): Use. // TODO(a.garipov): Use.
Verbose bool `yaml:"verbose"` Verbose bool `yaml:"verbose"`
} }
// type check // type check
var _ validator = (*logConfig)(nil) var _ validate.Interface = (*logConfig)(nil)
// validate implements the [validator] interface for *logConfig. // Validate implements the [validate.Interface] interface for *logConfig.
// //
// TODO(a.garipov): Add more validations. // TODO(a.garipov): Add more validations.
func (c *logConfig) validate() (err error) { func (c *logConfig) Validate() (err error) {
if c == nil { if c == nil {
return errors.ErrNoValue return errors.ErrNoValue
} }

View File

@@ -63,7 +63,7 @@ func Validate(fileName string) (err error) {
return err return err
} }
err = conf.validate() err = conf.Validate()
if err != nil { if err != nil {
return fmt.Errorf("validating config: %w", err) return fmt.Errorf("validating config: %w", err)
} }
@@ -105,7 +105,7 @@ func New(ctx context.Context, c *Config) (m *Manager, err error) {
return nil, err return nil, err
} }
err = conf.validate() err = conf.Validate()
if err != nil { if err != nil {
return nil, fmt.Errorf("validating config: %w", err) return nil, fmt.Errorf("validating config: %w", err)
} }
@@ -162,7 +162,7 @@ func (m *Manager) assemble(
BootstrapServers: conf.DNS.BootstrapDNS, BootstrapServers: conf.DNS.BootstrapDNS,
UpstreamServers: conf.DNS.UpstreamDNS, UpstreamServers: conf.DNS.UpstreamDNS,
DNS64Prefixes: conf.DNS.DNS64Prefixes, DNS64Prefixes: conf.DNS.DNS64Prefixes,
UpstreamTimeout: conf.DNS.UpstreamTimeout.Duration, UpstreamTimeout: time.Duration(conf.DNS.UpstreamTimeout),
BootstrapPreferIPv6: conf.DNS.BootstrapPreferIPv6, BootstrapPreferIPv6: conf.DNS.BootstrapPreferIPv6,
UseDNS64: conf.DNS.UseDNS64, UseDNS64: conf.DNS.UseDNS64,
} }
@@ -185,7 +185,7 @@ func (m *Manager) assemble(
Addresses: conf.HTTP.Addresses, Addresses: conf.HTTP.Addresses,
SecureAddresses: conf.HTTP.SecureAddresses, SecureAddresses: conf.HTTP.SecureAddresses,
OverrideAddress: webAddr, OverrideAddress: webAddr,
Timeout: conf.HTTP.Timeout.Duration, Timeout: time.Duration(conf.HTTP.Timeout),
ForceHTTPS: conf.HTTP.ForceHTTPS, ForceHTTPS: conf.HTTP.ForceHTTPS,
} }
@@ -266,7 +266,7 @@ func (m *Manager) updateCurrentDNS(c *dnssvc.Config) {
m.current.DNS.BootstrapDNS = slices.Clone(c.BootstrapServers) m.current.DNS.BootstrapDNS = slices.Clone(c.BootstrapServers)
m.current.DNS.UpstreamDNS = slices.Clone(c.UpstreamServers) m.current.DNS.UpstreamDNS = slices.Clone(c.UpstreamServers)
m.current.DNS.DNS64Prefixes = slices.Clone(c.DNS64Prefixes) m.current.DNS.DNS64Prefixes = slices.Clone(c.DNS64Prefixes)
m.current.DNS.UpstreamTimeout = timeutil.Duration{Duration: c.UpstreamTimeout} m.current.DNS.UpstreamTimeout = timeutil.Duration(c.UpstreamTimeout)
m.current.DNS.BootstrapPreferIPv6 = c.BootstrapPreferIPv6 m.current.DNS.BootstrapPreferIPv6 = c.BootstrapPreferIPv6
m.current.DNS.UseDNS64 = c.UseDNS64 m.current.DNS.UseDNS64 = c.UseDNS64
} }
@@ -318,6 +318,6 @@ func (m *Manager) updateCurrentWeb(c *websvc.Config) {
m.current.HTTP.Addresses = slices.Clone(c.Addresses) m.current.HTTP.Addresses = slices.Clone(c.Addresses)
m.current.HTTP.SecureAddresses = slices.Clone(c.SecureAddresses) m.current.HTTP.SecureAddresses = slices.Clone(c.SecureAddresses)
m.current.HTTP.Timeout = timeutil.Duration{Duration: c.Timeout} m.current.HTTP.Timeout = timeutil.Duration(c.Timeout)
m.current.HTTP.ForceHTTPS = c.ForceHTTPS m.current.HTTP.ForceHTTPS = c.ForceHTTPS
} }

View File

@@ -1,31 +0,0 @@
package configmgr
import (
"fmt"
"github.com/AdguardTeam/golibs/errors"
"github.com/AdguardTeam/golibs/timeutil"
"golang.org/x/exp/constraints"
)
// validator is the interface for configuration entities that can validate
// themselves.
type validator interface {
// validate returns an error if the entity isn't valid.
validate() (err error)
}
// numberOrDuration is the constraint for integer types along with
// timeutil.Duration.
type numberOrDuration interface {
constraints.Integer | timeutil.Duration
}
// newErrNotPositive returns an error about the value that must be positive but
// isn't. prop is the name of the property to mention in the error message.
//
// TODO(a.garipov): Consider moving such helpers to golibs and use in AdGuardDNS
// as well.
func newErrNotPositive[T numberOrDuration](prop string, v T) (err error) {
return fmt.Errorf("%s: %w, got %v", prop, errors.ErrNotPositive, v)
}

View File

@@ -0,0 +1,43 @@
// Package jsonpatch contains utilities for JSON Merge Patch APIs.
//
// See https://www.rfc-editor.org/rfc/rfc7396.
package jsonpatch
import (
"bytes"
"encoding/json"
"github.com/AdguardTeam/golibs/errors"
)
// NonRemovable is a type that prevents JSON null from being used to try and
// remove a value.
type NonRemovable[T any] struct {
Value T
IsSet bool
}
// type check
var _ json.Unmarshaler = (*NonRemovable[struct{}])(nil)
// UnmarshalJSON implements the [json.Unmarshaler] interface for *NonRemovable.
func (v *NonRemovable[T]) UnmarshalJSON(b []byte) (err error) {
if v == nil {
return errors.Error("jsonpatch.NonRemovable is nil")
}
if bytes.Equal(b, []byte("null")) {
return errors.Error("property cannot be removed")
}
v.IsSet = true
return json.Unmarshal(b, &v.Value)
}
// Set sets ptr if the value has been provided.
func (v NonRemovable[T]) Set(ptr *T) {
if v.IsSet {
*ptr = v.Value
}
}

View File

@@ -0,0 +1,29 @@
package jsonpatch_test
import (
"encoding/json"
"testing"
"github.com/AdguardTeam/AdGuardHome/internal/next/jsonpatch"
"github.com/AdguardTeam/golibs/testutil"
"github.com/stretchr/testify/assert"
)
func TestNonRemovable(t *testing.T) {
type T struct {
Value jsonpatch.NonRemovable[int] `json:"value"`
}
var v T
err := json.Unmarshal([]byte(`{"value":null}`), &v)
testutil.AssertErrorMsg(t, "property cannot be removed", err)
err = json.Unmarshal([]byte(`{"value":42}`), &v)
assert.NoError(t, err)
var got int
v.Value.Set(&got)
assert.Equal(t, 42, got)
}

View File

@@ -5,10 +5,9 @@ import (
"fmt" "fmt"
"net/http" "net/http"
"net/netip" "net/netip"
"time"
"github.com/AdguardTeam/AdGuardHome/internal/aghhttp" "github.com/AdguardTeam/AdGuardHome/internal/aghhttp"
"github.com/AdguardTeam/AdGuardHome/internal/next/dnssvc" "github.com/AdguardTeam/AdGuardHome/internal/next/jsonpatch"
) )
// ReqPatchSettingsDNS describes the request to the PATCH /api/v1/settings/dns // ReqPatchSettingsDNS describes the request to the PATCH /api/v1/settings/dns
@@ -16,13 +15,15 @@ import (
type ReqPatchSettingsDNS struct { type ReqPatchSettingsDNS struct {
// TODO(a.garipov): Add more as we go. // TODO(a.garipov): Add more as we go.
Addresses []netip.AddrPort `json:"addresses"` Addresses jsonpatch.NonRemovable[[]netip.AddrPort] `json:"addresses"`
BootstrapServers []string `json:"bootstrap_servers"` BootstrapServers jsonpatch.NonRemovable[[]string] `json:"bootstrap_servers"`
UpstreamServers []string `json:"upstream_servers"` UpstreamServers jsonpatch.NonRemovable[[]string] `json:"upstream_servers"`
DNS64Prefixes []netip.Prefix `json:"dns64_prefixes"` DNS64Prefixes jsonpatch.NonRemovable[[]netip.Prefix] `json:"dns64_prefixes"`
UpstreamTimeout aghhttp.JSONDuration `json:"upstream_timeout"`
BootstrapPreferIPv6 bool `json:"bootstrap_prefer_ipv6"` UpstreamTimeout jsonpatch.NonRemovable[aghhttp.JSONDuration] `json:"upstream_timeout"`
UseDNS64 bool `json:"use_dns64"`
BootstrapPreferIPv6 jsonpatch.NonRemovable[bool] `json:"bootstrap_prefer_ipv6"`
UseDNS64 jsonpatch.NonRemovable[bool] `json:"use_dns64"`
} }
// HTTPAPIDNSSettings are the DNS settings as used by the HTTP API. See the // HTTPAPIDNSSettings are the DNS settings as used by the HTTP API. See the
@@ -42,13 +43,7 @@ type HTTPAPIDNSSettings struct {
// handlePatchSettingsDNS is the handler for the PATCH /api/v1/settings/dns HTTP // handlePatchSettingsDNS is the handler for the PATCH /api/v1/settings/dns HTTP
// API. // API.
func (svc *Service) handlePatchSettingsDNS(w http.ResponseWriter, r *http.Request) { func (svc *Service) handlePatchSettingsDNS(w http.ResponseWriter, r *http.Request) {
req := &ReqPatchSettingsDNS{ req := &ReqPatchSettingsDNS{}
Addresses: []netip.AddrPort{},
BootstrapServers: []string{},
UpstreamServers: []string{},
}
// TODO(a.garipov): Validate nulls and proper JSON patch.
err := json.NewDecoder(r.Body).Decode(&req) err := json.NewDecoder(r.Body).Decode(&req)
if err != nil { if err != nil {
@@ -57,16 +52,20 @@ func (svc *Service) handlePatchSettingsDNS(w http.ResponseWriter, r *http.Reques
return return
} }
newConf := &dnssvc.Config{ dnsSvc := svc.confMgr.DNS()
Logger: svc.logger, newConf := dnsSvc.Config()
Addresses: req.Addresses,
BootstrapServers: req.BootstrapServers, // TODO(a.garipov): Add more as we go.
UpstreamServers: req.UpstreamServers,
DNS64Prefixes: req.DNS64Prefixes, req.Addresses.Set(&newConf.Addresses)
UpstreamTimeout: time.Duration(req.UpstreamTimeout), req.BootstrapServers.Set(&newConf.BootstrapServers)
BootstrapPreferIPv6: req.BootstrapPreferIPv6, req.UpstreamServers.Set(&newConf.UpstreamServers)
UseDNS64: req.UseDNS64, req.DNS64Prefixes.Set(&newConf.DNS64Prefixes)
}
req.UpstreamTimeout.Set((*aghhttp.JSONDuration)(&newConf.UpstreamTimeout))
req.BootstrapPreferIPv6.Set(&newConf.BootstrapPreferIPv6)
req.UseDNS64.Set(&newConf.UseDNS64)
ctx := r.Context() ctx := r.Context()
err = svc.confMgr.UpdateDNS(ctx, newConf) err = svc.confMgr.UpdateDNS(ctx, newConf)

View File

@@ -41,7 +41,7 @@ func TestService_HandlePatchSettingsDNS(t *testing.T) {
return nil return nil
}, },
OnShutdown: func(_ context.Context) (err error) { panic("not implemented") }, OnShutdown: func(_ context.Context) (err error) { panic("not implemented") },
OnConfig: func() (c *dnssvc.Config) { panic("not implemented") }, OnConfig: func() (c *dnssvc.Config) { return &dnssvc.Config{} },
} }
} }
confMgr.onUpdateDNS = func(ctx context.Context, c *dnssvc.Config) (err error) { confMgr.onUpdateDNS = func(ctx context.Context, c *dnssvc.Config) (err error) {

View File

@@ -10,6 +10,7 @@ import (
"github.com/AdguardTeam/AdGuardHome/internal/aghhttp" "github.com/AdguardTeam/AdGuardHome/internal/aghhttp"
"github.com/AdguardTeam/AdGuardHome/internal/next/agh" "github.com/AdguardTeam/AdGuardHome/internal/next/agh"
"github.com/AdguardTeam/AdGuardHome/internal/next/jsonpatch"
"github.com/AdguardTeam/golibs/logutil/slogutil" "github.com/AdguardTeam/golibs/logutil/slogutil"
) )
@@ -20,9 +21,12 @@ type ReqPatchSettingsHTTP struct {
// //
// TODO(a.garipov): Add wait time. // TODO(a.garipov): Add wait time.
Addresses []netip.AddrPort `json:"addresses"` Addresses jsonpatch.NonRemovable[[]netip.AddrPort] `json:"addresses"`
SecureAddresses []netip.AddrPort `json:"secure_addresses"` SecureAddresses jsonpatch.NonRemovable[[]netip.AddrPort] `json:"secure_addresses"`
Timeout aghhttp.JSONDuration `json:"timeout"`
Timeout jsonpatch.NonRemovable[aghhttp.JSONDuration] `json:"timeout"`
ForceHTTPS jsonpatch.NonRemovable[bool] `json:"force_https"`
} }
// HTTPAPIHTTPSettings are the HTTP settings as used by the HTTP API. See the // HTTPAPIHTTPSettings are the HTTP settings as used by the HTTP API. See the
@@ -41,8 +45,6 @@ type HTTPAPIHTTPSettings struct {
func (svc *Service) handlePatchSettingsHTTP(w http.ResponseWriter, r *http.Request) { func (svc *Service) handlePatchSettingsHTTP(w http.ResponseWriter, r *http.Request) {
req := &ReqPatchSettingsHTTP{} req := &ReqPatchSettingsHTTP{}
// TODO(a.garipov): Validate nulls and proper JSON patch.
err := json.NewDecoder(r.Body).Decode(&req) err := json.NewDecoder(r.Body).Decode(&req)
if err != nil { if err != nil {
aghhttp.WriteJSONResponseError(w, r, fmt.Errorf("decoding: %w", err)) aghhttp.WriteJSONResponseError(w, r, fmt.Errorf("decoding: %w", err))
@@ -50,20 +52,14 @@ func (svc *Service) handlePatchSettingsHTTP(w http.ResponseWriter, r *http.Reque
return return
} }
newConf := &Config{ newConf := svc.Config()
Logger: svc.logger,
Pprof: &PprofConfig{ // TODO(a.garipov): Add more as we go.
Port: svc.pprofPort,
Enabled: svc.pprof != nil, req.Addresses.Set(&newConf.Addresses)
}, req.SecureAddresses.Set(&newConf.SecureAddresses)
ConfigManager: svc.confMgr, req.Timeout.Set((*aghhttp.JSONDuration)(&newConf.Timeout))
Frontend: svc.frontend, req.ForceHTTPS.Set(&newConf.ForceHTTPS)
TLS: svc.tls,
Addresses: req.Addresses,
SecureAddresses: req.SecureAddresses,
Timeout: time.Duration(req.Timeout),
ForceHTTPS: svc.forceHTTPS,
}
aghhttp.WriteJSONResponseOK(w, r, &HTTPAPIHTTPSettings{ aghhttp.WriteJSONResponseOK(w, r, &HTTPAPIHTTPSettings{
Addresses: newConf.Addresses, Addresses: newConf.Addresses,

View File

@@ -163,8 +163,8 @@ func (w *Weekly) UnmarshalYAML(value *yaml.Node) (err error) {
} }
for i, d := range days { for i, d := range days {
r := dayRange{ r := dayRange{
start: d.Start.Duration, start: time.Duration(d.Start),
end: d.End.Duration, end: time.Duration(d.End),
} }
err = w.validate(r) err = w.validate(r)
@@ -255,32 +255,32 @@ func (w *Weekly) MarshalYAML() (v any, err error) {
return weeklyConfigYAML{ return weeklyConfigYAML{
TimeZone: w.location.String(), TimeZone: w.location.String(),
Sunday: dayConfigYAML{ Sunday: dayConfigYAML{
Start: timeutil.Duration{Duration: w.days[time.Sunday].start}, Start: timeutil.Duration(w.days[time.Sunday].start),
End: timeutil.Duration{Duration: w.days[time.Sunday].end}, End: timeutil.Duration(w.days[time.Sunday].end),
}, },
Monday: dayConfigYAML{ Monday: dayConfigYAML{
Start: timeutil.Duration{Duration: w.days[time.Monday].start}, Start: timeutil.Duration(w.days[time.Monday].start),
End: timeutil.Duration{Duration: w.days[time.Monday].end}, End: timeutil.Duration(w.days[time.Monday].end),
}, },
Tuesday: dayConfigYAML{ Tuesday: dayConfigYAML{
Start: timeutil.Duration{Duration: w.days[time.Tuesday].start}, Start: timeutil.Duration(w.days[time.Tuesday].start),
End: timeutil.Duration{Duration: w.days[time.Tuesday].end}, End: timeutil.Duration(w.days[time.Tuesday].end),
}, },
Wednesday: dayConfigYAML{ Wednesday: dayConfigYAML{
Start: timeutil.Duration{Duration: w.days[time.Wednesday].start}, Start: timeutil.Duration(w.days[time.Wednesday].start),
End: timeutil.Duration{Duration: w.days[time.Wednesday].end}, End: timeutil.Duration(w.days[time.Wednesday].end),
}, },
Thursday: dayConfigYAML{ Thursday: dayConfigYAML{
Start: timeutil.Duration{Duration: w.days[time.Thursday].start}, Start: timeutil.Duration(w.days[time.Thursday].start),
End: timeutil.Duration{Duration: w.days[time.Thursday].end}, End: timeutil.Duration(w.days[time.Thursday].end),
}, },
Friday: dayConfigYAML{ Friday: dayConfigYAML{
Start: timeutil.Duration{Duration: w.days[time.Friday].start}, Start: timeutil.Duration(w.days[time.Friday].start),
End: timeutil.Duration{Duration: w.days[time.Friday].end}, End: timeutil.Duration(w.days[time.Friday].end),
}, },
Saturday: dayConfigYAML{ Saturday: dayConfigYAML{
Start: timeutil.Duration{Duration: w.days[time.Saturday].start}, Start: timeutil.Duration(w.days[time.Saturday].start),
End: timeutil.Duration{Duration: w.days[time.Saturday].end}, End: timeutil.Duration(w.days[time.Saturday].end),
}, },
}, nil }, nil
} }

View File

@@ -63,11 +63,7 @@ func (s *StatsCtx) handleStats(w http.ResponseWriter, r *http.Request) {
resp, ok = s.getData(uint32(s.limit.Hours())) resp, ok = s.getData(uint32(s.limit.Hours()))
}() }()
s.logger.DebugContext( s.logger.DebugContext(ctx, "prepared data", "elapsed", time.Since(start))
ctx,
"prepared data",
"elapsed", timeutil.Duration{Duration: time.Since(start)},
)
if !ok { if !ok {
// Don't bring the message to the lower case since it's a part of UI // Don't bring the message to the lower case since it's a part of UI

View File

@@ -1,6 +1,6 @@
module github.com/AdguardTeam/AdGuardHome/internal/tools module github.com/AdguardTeam/AdGuardHome/internal/tools
go 1.23.4 go 1.23.5
require ( require (
github.com/fzipp/gocyclo v0.6.0 github.com/fzipp/gocyclo v0.6.0
@@ -9,8 +9,8 @@ require (
github.com/jstemmer/go-junit-report/v2 v2.1.0 github.com/jstemmer/go-junit-report/v2 v2.1.0
github.com/kisielk/errcheck v1.8.0 github.com/kisielk/errcheck v1.8.0
github.com/securego/gosec/v2 v2.21.4 github.com/securego/gosec/v2 v2.21.4
github.com/uudashr/gocognit v1.1.3 github.com/uudashr/gocognit v1.2.0
golang.org/x/tools v0.27.0 golang.org/x/tools v0.28.0
golang.org/x/vuln v1.1.3 golang.org/x/vuln v1.1.3
honnef.co/go/tools v0.5.1 honnef.co/go/tools v0.5.1
mvdan.cc/gofumpt v0.7.0 mvdan.cc/gofumpt v0.7.0
@@ -21,7 +21,7 @@ require (
require ( require (
cloud.google.com/go v0.116.0 // indirect cloud.google.com/go v0.116.0 // indirect
cloud.google.com/go/ai v0.9.0 // indirect cloud.google.com/go/ai v0.9.0 // indirect
cloud.google.com/go/auth v0.11.0 // indirect cloud.google.com/go/auth v0.12.1 // indirect
cloud.google.com/go/auth/oauth2adapt v0.2.6 // indirect cloud.google.com/go/auth/oauth2adapt v0.2.6 // indirect
cloud.google.com/go/compute/metadata v0.5.2 // indirect cloud.google.com/go/compute/metadata v0.5.2 // indirect
cloud.google.com/go/longrunning v0.6.3 // indirect cloud.google.com/go/longrunning v0.6.3 // indirect
@@ -30,8 +30,7 @@ require (
github.com/felixge/httpsnoop v1.0.4 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect github.com/google/generative-ai-go v0.19.0 // indirect
github.com/google/generative-ai-go v0.18.0 // indirect
github.com/google/go-cmp v0.6.0 // indirect github.com/google/go-cmp v0.6.0 // indirect
github.com/google/renameio/v2 v2.0.0 // indirect github.com/google/renameio/v2 v2.0.0 // indirect
github.com/google/s2a-go v0.1.8 // indirect github.com/google/s2a-go v0.1.8 // indirect
@@ -41,28 +40,27 @@ require (
github.com/gookit/color v1.5.4 // indirect github.com/gookit/color v1.5.4 // indirect
github.com/rogpeppe/go-internal v1.13.1 // indirect github.com/rogpeppe/go-internal v1.13.1 // indirect
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.57.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.57.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.57.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.57.0 // indirect
go.opentelemetry.io/otel v1.32.0 // indirect go.opentelemetry.io/otel v1.32.0 // indirect
go.opentelemetry.io/otel/metric v1.32.0 // indirect go.opentelemetry.io/otel/metric v1.32.0 // indirect
go.opentelemetry.io/otel/trace v1.32.0 // indirect go.opentelemetry.io/otel/trace v1.32.0 // indirect
golang.org/x/crypto v0.29.0 // indirect golang.org/x/crypto v0.31.0 // indirect
golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f // indirect golang.org/x/exp v0.0.0-20241210194714-1829a127f884 // indirect
golang.org/x/exp/typeparams v0.0.0-20241108190413-2d47ceb2692f // indirect golang.org/x/exp/typeparams v0.0.0-20241210194714-1829a127f884 // indirect
golang.org/x/mod v0.22.0 // indirect golang.org/x/mod v0.22.0 // indirect
golang.org/x/net v0.31.0 // indirect golang.org/x/net v0.32.0 // indirect
golang.org/x/oauth2 v0.24.0 // indirect golang.org/x/oauth2 v0.24.0 // indirect
golang.org/x/sync v0.9.0 // indirect golang.org/x/sync v0.10.0 // indirect
golang.org/x/sys v0.27.0 // indirect golang.org/x/sys v0.28.0 // indirect
golang.org/x/telemetry v0.0.0-20241108154256-525ce2e96f55 // indirect golang.org/x/telemetry v0.0.0-20241204182053-c0ac0e154df3 // indirect
golang.org/x/term v0.26.0 // indirect golang.org/x/term v0.27.0 // indirect
golang.org/x/text v0.20.0 // indirect golang.org/x/text v0.21.0 // indirect
golang.org/x/time v0.8.0 // indirect golang.org/x/time v0.8.0 // indirect
google.golang.org/api v0.209.0 // indirect google.golang.org/api v0.211.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20241202173237-19429a94021a // indirect google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20241209162323-e6fa225c2576 // indirect
google.golang.org/grpc v1.68.0 // indirect google.golang.org/grpc v1.68.1 // indirect
google.golang.org/protobuf v1.35.2 // indirect google.golang.org/protobuf v1.35.2 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
mvdan.cc/editorconfig v0.3.0 // indirect mvdan.cc/editorconfig v0.3.0 // indirect

View File

@@ -1,31 +1,21 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.116.0 h1:B3fRrSDkLRt5qSHWe40ERJvhvnQwdZiHu0bJOpldweE= cloud.google.com/go v0.116.0 h1:B3fRrSDkLRt5qSHWe40ERJvhvnQwdZiHu0bJOpldweE=
cloud.google.com/go v0.116.0/go.mod h1:cEPSRWPzZEswwdr9BxE6ChEn01dWlTaF05LiC2Xs70U= cloud.google.com/go v0.116.0/go.mod h1:cEPSRWPzZEswwdr9BxE6ChEn01dWlTaF05LiC2Xs70U=
cloud.google.com/go/ai v0.9.0 h1:r1Ig8O8+Qr3Ia3WfoO+gokD0fxB2Rk4quppuKjmGMsY= cloud.google.com/go/ai v0.9.0 h1:r1Ig8O8+Qr3Ia3WfoO+gokD0fxB2Rk4quppuKjmGMsY=
cloud.google.com/go/ai v0.9.0/go.mod h1:28bKM/oxmRgxmRgI1GLumFv+NSkt+DscAg/gF+54zzY= cloud.google.com/go/ai v0.9.0/go.mod h1:28bKM/oxmRgxmRgI1GLumFv+NSkt+DscAg/gF+54zzY=
cloud.google.com/go/auth v0.11.0 h1:Ic5SZz2lsvbYcWT5dfjNWgw6tTlGi2Wc8hyQSC9BstA= cloud.google.com/go/auth v0.12.1 h1:n2Bj25BUMM0nvE9D2XLTiImanwZhO3DkfWSYS/SAJP4=
cloud.google.com/go/auth v0.11.0/go.mod h1:xxA5AqpDrvS+Gkmo9RqrGGRh6WSNKKOXhY3zNOr38tI= cloud.google.com/go/auth v0.12.1/go.mod h1:BFMu+TNpF3DmvfBO9ClqTR/SiqVIm7LukKF9mbendF4=
cloud.google.com/go/auth/oauth2adapt v0.2.6 h1:V6a6XDu2lTwPZWOawrAa9HUK+DB2zfJyTuciBG5hFkU= cloud.google.com/go/auth/oauth2adapt v0.2.6 h1:V6a6XDu2lTwPZWOawrAa9HUK+DB2zfJyTuciBG5hFkU=
cloud.google.com/go/auth/oauth2adapt v0.2.6/go.mod h1:AlmsELtlEBnaNTL7jCj8VQFLy6mbZv0s4Q7NGBeQ5E8= cloud.google.com/go/auth/oauth2adapt v0.2.6/go.mod h1:AlmsELtlEBnaNTL7jCj8VQFLy6mbZv0s4Q7NGBeQ5E8=
cloud.google.com/go/compute/metadata v0.5.2 h1:UxK4uu/Tn+I3p2dYWTfiX4wva7aYlKixAHn3fyqngqo= cloud.google.com/go/compute/metadata v0.5.2 h1:UxK4uu/Tn+I3p2dYWTfiX4wva7aYlKixAHn3fyqngqo=
cloud.google.com/go/compute/metadata v0.5.2/go.mod h1:C66sj2AluDcIqakBq/M8lw8/ybHgOZqin2obFxa/E5k= cloud.google.com/go/compute/metadata v0.5.2/go.mod h1:C66sj2AluDcIqakBq/M8lw8/ybHgOZqin2obFxa/E5k=
cloud.google.com/go/longrunning v0.6.3 h1:A2q2vuyXysRcwzqDpMMLSI6mb6o39miS52UEG/Rd2ng= cloud.google.com/go/longrunning v0.6.3 h1:A2q2vuyXysRcwzqDpMMLSI6mb6o39miS52UEG/Rd2ng=
cloud.google.com/go/longrunning v0.6.3/go.mod h1:k/vIs83RN4bE3YCswdXC5PFfWVILjm3hpEUlSko4PiI= cloud.google.com/go/longrunning v0.6.3/go.mod h1:k/vIs83RN4bE3YCswdXC5PFfWVILjm3hpEUlSko4PiI=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c h1:pxW6RcqyfI9/kWtOwnv/G+AzdKuy2ZrqINhenH4HyNs= github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c h1:pxW6RcqyfI9/kWtOwnv/G+AzdKuy2ZrqINhenH4HyNs=
github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
github.com/ccojocar/zxcvbn-go v1.0.2 h1:na/czXU8RrhXO4EZme6eQJLR4PzcGsahsBOAwU6I3Vg= github.com/ccojocar/zxcvbn-go v1.0.2 h1:na/czXU8RrhXO4EZme6eQJLR4PzcGsahsBOAwU6I3Vg=
github.com/ccojocar/zxcvbn-go v1.0.2/go.mod h1:g1qkXtUSvHP8lhHp5GrSmTz6uWALGRMQdw6Qnz/hi60= github.com/ccojocar/zxcvbn-go v1.0.2/go.mod h1:g1qkXtUSvHP8lhHp5GrSmTz6uWALGRMQdw6Qnz/hi60=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/fzipp/gocyclo v0.6.0 h1:lsblElZG7d3ALtGMx9fmxeTKZaLLpU8mET09yN4BBLo= github.com/fzipp/gocyclo v0.6.0 h1:lsblElZG7d3ALtGMx9fmxeTKZaLLpU8mET09yN4BBLo=
@@ -39,34 +29,14 @@ github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7
github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow= github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow=
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ=
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/golangci/misspell v0.6.0 h1:JCle2HUTNWirNlDIAUO44hUsKhOFqGPoC4LZxlaSXDs= github.com/golangci/misspell v0.6.0 h1:JCle2HUTNWirNlDIAUO44hUsKhOFqGPoC4LZxlaSXDs=
github.com/golangci/misspell v0.6.0/go.mod h1:keMNyY6R9isGaSAu+4Q8NMBwMPkh15Gtc8UCVoDtAWo= github.com/golangci/misspell v0.6.0/go.mod h1:keMNyY6R9isGaSAu+4Q8NMBwMPkh15Gtc8UCVoDtAWo=
github.com/google/generative-ai-go v0.18.0 h1:6ybg9vOCLcI/UpBBYXOTVgvKmcUKFRNj+2Cj3GnebSo= github.com/google/generative-ai-go v0.19.0 h1:R71szggh8wHMCUlEMsW2A/3T+5LdEIkiaHSYgSpUgdg=
github.com/google/generative-ai-go v0.18.0/go.mod h1:JYolL13VG7j79kM5BtHz4qwONHkeJQzOCkKXnpqtS/E= github.com/google/generative-ai-go v0.19.0/go.mod h1:JYolL13VG7j79kM5BtHz4qwONHkeJQzOCkKXnpqtS/E=
github.com/google/go-cmdtest v0.4.1-0.20220921163831-55ab3332a786 h1:rcv+Ippz6RAtvaGgKxc+8FQIpxHgsF+HBzPyYL2cyVU= github.com/google/go-cmdtest v0.4.1-0.20220921163831-55ab3332a786 h1:rcv+Ippz6RAtvaGgKxc+8FQIpxHgsF+HBzPyYL2cyVU=
github.com/google/go-cmdtest v0.4.1-0.20220921163831-55ab3332a786/go.mod h1:apVn/GCasLZUVpAJ6oWAuyP7Ne7CEsQbTnc0plM3m+o= github.com/google/go-cmdtest v0.4.1-0.20220921163831-55ab3332a786/go.mod h1:apVn/GCasLZUVpAJ6oWAuyP7Ne7CEsQbTnc0plM3m+o=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
@@ -78,7 +48,6 @@ github.com/google/renameio/v2 v2.0.0 h1:UifI23ZTGY8Tt29JbYFiuyIU3eX+RNFtUwefq9qA
github.com/google/renameio/v2 v2.0.0/go.mod h1:BtmJXm5YlszgC+TD4HOEEUFgkJP3nLxehU6hfe7jRt4= github.com/google/renameio/v2 v2.0.0/go.mod h1:BtmJXm5YlszgC+TD4HOEEUFgkJP3nLxehU6hfe7jRt4=
github.com/google/s2a-go v0.1.8 h1:zZDs9gcbt9ZPLV0ndSyQk6Kacx2g/X+SKYovpnz3SMM= github.com/google/s2a-go v0.1.8 h1:zZDs9gcbt9ZPLV0ndSyQk6Kacx2g/X+SKYovpnz3SMM=
github.com/google/s2a-go v0.1.8/go.mod h1:6iNWHTpQ+nfNRN5E00MSdfDwVesa8hhS32PhPO8deJA= github.com/google/s2a-go v0.1.8/go.mod h1:6iNWHTpQ+nfNRN5E00MSdfDwVesa8hhS32PhPO8deJA=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/enterprise-certificate-proxy v0.3.4 h1:XYIDZApgAnrN1c855gTgghdIA6Stxb52D5RnLI1SLyw= github.com/googleapis/enterprise-certificate-proxy v0.3.4 h1:XYIDZApgAnrN1c855gTgghdIA6Stxb52D5RnLI1SLyw=
@@ -103,28 +72,19 @@ github.com/onsi/gomega v1.34.2 h1:pNCwDkzrsv7MS9kpaQvVb1aVLahQXyJ/Tv5oAZMI3i8=
github.com/onsi/gomega v1.34.2/go.mod h1:v1xfxRgk0KIsG+QOdm7p8UosrOzPYRo60fd3B/1Dukc= github.com/onsi/gomega v1.34.2/go.mod h1:v1xfxRgk0KIsG+QOdm7p8UosrOzPYRo60fd3B/1Dukc=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
github.com/securego/gosec/v2 v2.21.4 h1:Le8MSj0PDmOnHJgUATjD96PaXRvCpKC+DGJvwyy0Mlk= github.com/securego/gosec/v2 v2.21.4 h1:Le8MSj0PDmOnHJgUATjD96PaXRvCpKC+DGJvwyy0Mlk=
github.com/securego/gosec/v2 v2.21.4/go.mod h1:Jtb/MwRQfRxCXyCm1rfM1BEiiiTfUOdyzzAhlr6lUTA= github.com/securego/gosec/v2 v2.21.4/go.mod h1:Jtb/MwRQfRxCXyCm1rfM1BEiiiTfUOdyzzAhlr6lUTA=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/uudashr/gocognit v1.1.3 h1:l+a111VcDbKfynh+airAy/DJQKaXh2m9vkoysMPSZyM= github.com/uudashr/gocognit v1.2.0 h1:3BU9aMr1xbhPlvJLSydKwdLN3tEUUrzPSSM8S4hDYRA=
github.com/uudashr/gocognit v1.1.3/go.mod h1:aKH8/e8xbTRBwjbCkwZ8qt4l2EpKXl31KMHgSS+lZ2U= github.com/uudashr/gocognit v1.2.0/go.mod h1:k/DdKPI6XBZO1q7HgoV2juESI2/Ofj9AcHPZhBBdrTU=
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM= github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.57.0 h1:qtFISDHKolvIxzSs0gIaiPUPR0Cucb0F2coHC7ZLdps= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.57.0 h1:qtFISDHKolvIxzSs0gIaiPUPR0Cucb0F2coHC7ZLdps=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.57.0/go.mod h1:Y+Pop1Q6hCOnETWTW4NROK/q1hv50hM7yDaUTjG8lp8= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.57.0/go.mod h1:Y+Pop1Q6hCOnETWTW4NROK/q1hv50hM7yDaUTjG8lp8=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.57.0 h1:DheMAlT6POBP+gh8RUH19EOTnQIor5QE0uSRPtzCpSw= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.57.0 h1:DheMAlT6POBP+gh8RUH19EOTnQIor5QE0uSRPtzCpSw=
@@ -137,110 +97,68 @@ go.opentelemetry.io/otel/trace v1.32.0 h1:WIC9mYrXf8TmY/EXuULKc8hR17vE+Hjv2cssQD
go.opentelemetry.io/otel/trace v1.32.0/go.mod h1:+i4rkvCraA+tG6AzwloGaCtkx53Fa+L+V8e9a7YvhT8= go.opentelemetry.io/otel/trace v1.32.0/go.mod h1:+i4rkvCraA+tG6AzwloGaCtkx53Fa+L+V8e9a7YvhT8=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ= golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg= golang.org/x/exp v0.0.0-20241210194714-1829a127f884 h1:Y/Mj/94zIQQGHVSv1tTtQBDaQaJe62U9bkDZKKyhPCU=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20241210194714-1829a127f884/go.mod h1:qj5a5QZpwLU2NLQudwIN5koi3beDhSAlJwa67PuM98c=
golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f h1:XdNn9LlyWAhLVp6P/i8QYBW+hlyhrhei9uErw2B5GJo= golang.org/x/exp/typeparams v0.0.0-20241210194714-1829a127f884 h1:1xaZTydL5Gsg78QharTwKfA9FY9CZ1VQj6D/AZEvHR0=
golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f/go.mod h1:D5SMRVC3C2/4+F/DB1wZsLRnSNimn2Sp/NPsCrsv8ak= golang.org/x/exp/typeparams v0.0.0-20241210194714-1829a127f884/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk=
golang.org/x/exp/typeparams v0.0.0-20241108190413-2d47ceb2692f h1:WTyX8eCCyfdqiPYkRGm0MqElSfYFH3yR1+rl/mct9sA=
golang.org/x/exp/typeparams v0.0.0-20241108190413-2d47ceb2692f/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4= golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4=
golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo= golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI=
golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM= golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.24.0 h1:KTBBxWqUa0ykRPLtV69rRto9TLXcqYkeswu48x/gvNE= golang.org/x/oauth2 v0.24.0 h1:KTBBxWqUa0ykRPLtV69rRto9TLXcqYkeswu48x/gvNE=
golang.org/x/oauth2 v0.24.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/oauth2 v0.24.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ= golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/telemetry v0.0.0-20241108154256-525ce2e96f55 h1:ZZOVC4W26kVZSAW314SD81pWtiRgWNMbZsgLqKXx9lE= golang.org/x/telemetry v0.0.0-20241204182053-c0ac0e154df3 h1:rCLsPBq7l0E9Z451UgkWFkaWYhgt7dGmAlpD6hLjK5I=
golang.org/x/telemetry v0.0.0-20241108154256-525ce2e96f55/go.mod h1:7Vh679jcBo81KQrd4wo0gKov7BE6IHwu1tEhHxHNM30= golang.org/x/telemetry v0.0.0-20241204182053-c0ac0e154df3/go.mod h1:8h4Hgq+jcTvCDv2+i7NrfWwpYHcESleo2nGHxLbFLJ4=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.26.0 h1:WEQa6V3Gja/BhNxg540hBip/kkaYtRg3cxg4oXSw4AU= golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q=
golang.org/x/term v0.26.0/go.mod h1:Si5m1o57C5nBNQo5z1iq+XDijt21BDBDp2bK0QI8e3E= golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg= golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg=
golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.27.0 h1:qEKojBykQkQ4EynWy4S8Weg69NumxKdn40Fce3uc/8o= golang.org/x/tools v0.28.0 h1:WuB6qZ4RPCQo5aP3WdKZS7i595EdWqWR8vqJTlwTVK8=
golang.org/x/tools v0.27.0/go.mod h1:sUi0ZgbwW9ZPAq26Ekut+weQPR5eIM6GQLQ1Yjm1H0Q= golang.org/x/tools v0.28.0/go.mod h1:dcIOrVd3mfQKTgrDVQHqCPMWy6lnhfhtX3hLXYVLfRw=
golang.org/x/vuln v1.1.3 h1:NPGnvPOTgnjBc9HTaUx+nj+EaUYxl5SJOWqaDYGaFYw= golang.org/x/vuln v1.1.3 h1:NPGnvPOTgnjBc9HTaUx+nj+EaUYxl5SJOWqaDYGaFYw=
golang.org/x/vuln v1.1.3/go.mod h1:7Le6Fadm5FOqE9C926BCD0g12NWyhg7cxV4BwcPFuNY= golang.org/x/vuln v1.1.3/go.mod h1:7Le6Fadm5FOqE9C926BCD0g12NWyhg7cxV4BwcPFuNY=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/api v0.209.0 h1:Ja2OXNlyRlWCWu8o+GgI4yUn/wz9h/5ZfFbKz+dQX+w= google.golang.org/api v0.211.0 h1:IUpLjq09jxBSV1lACO33CGY3jsRcbctfGzhj+ZSE/Bg=
google.golang.org/api v0.209.0/go.mod h1:I53S168Yr/PNDNMi5yPnDc0/LGRZO6o7PoEbl/HY3CM= google.golang.org/api v0.211.0/go.mod h1:XOloB4MXFH4UTlQSGuNUxw0UT74qdENK8d6JNsXKLi0=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576 h1:CkkIfIt50+lT6NHAVoRYEyAvQGFM7xEwXUUywFvEb3Q=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576/go.mod h1:1R3kvZ1dtP3+4p4d3G8uJ8rFk/fWlScl38vanWACI08=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto/googleapis/rpc v0.0.0-20241209162323-e6fa225c2576 h1:8ZmaLZE4XWrtU3MyClkYqqtl6Oegr3235h7jxsDyqCY=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto/googleapis/rpc v0.0.0-20241209162323-e6fa225c2576/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/grpc v1.68.1 h1:oI5oTa11+ng8r8XMMN7jAOmWfPZWbYpCFaMUTACxkM0=
google.golang.org/genproto/googleapis/api v0.0.0-20241202173237-19429a94021a h1:OAiGFfOiA0v9MRYsSidp3ubZaBnteRUyn3xB2ZQ5G/E= google.golang.org/grpc v1.68.1/go.mod h1:+q1XYFJjShcqn0QZHvCyeR4CXPA+llXIeUIfIe00waw=
google.golang.org/genproto/googleapis/api v0.0.0-20241202173237-19429a94021a/go.mod h1:jehYqy3+AhJU9ve55aNOaSml7wUXjF9x6z2LcCfpAhY=
google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a h1:hgh8P4EuoxpsuKMXX/To36nOFD7vixReXgn8lPGnt+o=
google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
google.golang.org/grpc v1.68.0 h1:aHQeeJbo8zAkAa3pRzrVjZlbz6uSfeOXlJNQM0RAbz0=
google.golang.org/grpc v1.68.0/go.mod h1:fmSPC5AsjSBCK54MyHRx48kpOti1/jRfOlwEWywNjWA=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.35.2 h1:8Ar7bF+apOIoThw1EdZl0p1oWvMqTHmpA2fRTyZO8io= google.golang.org/protobuf v1.35.2 h1:8Ar7bF+apOIoThw1EdZl0p1oWvMqTHmpA2fRTyZO8io=
google.golang.org/protobuf v1.35.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= google.golang.org/protobuf v1.35.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.5.1 h1:4bH5o3b5ZULQ4UrBmP+63W9r7qIkqJClEA9ko5YKx+I= honnef.co/go/tools v0.5.1 h1:4bH5o3b5ZULQ4UrBmP+63W9r7qIkqJClEA9ko5YKx+I=
honnef.co/go/tools v0.5.1/go.mod h1:e9irvo83WDG9/irijV44wr3tbhcFeRnfpVlRqVwpzMs= honnef.co/go/tools v0.5.1/go.mod h1:e9irvo83WDG9/irijV44wr3tbhcFeRnfpVlRqVwpzMs=
mvdan.cc/editorconfig v0.3.0 h1:D1D2wLYEYGpawWT5SpM5pRivgEgXjtEXwC9MWhEY0gQ= mvdan.cc/editorconfig v0.3.0 h1:D1D2wLYEYGpawWT5SpM5pRivgEgXjtEXwC9MWhEY0gQ=

File diff suppressed because it is too large Load Diff

View File

@@ -1,35 +1,27 @@
# AdGuard Home OpenAPI # AdGuard Home OpenAPI
We are using We are using [OpenAPI specification](https://swagger.io/docs/specification/about/) to generate AdGuard Home API specification.
[OpenAPI specification](https://swagger.io/docs/specification/about/)
to generate AdGuard Home API specification.
## How To Edit The API Spec ## How to edit the API spec
The easiest way would be to use The easiest way would be to use [Swagger Editor](http://editor.swagger.io/) and just copy/paste the YAML file there.
[Swagger Editor](http://editor.swagger.io/)
and just copy/paste the YAML file there.
## How To Read The API Doc ## How to read the API doc
1. `yarn install` 1. `yarn install`
2. `yarn start` 2. `yarn start`
3. Open `http://localhost:4000/` 3. open `http://localhost:4000/`
## Changelog ## Changelog
[Here](CHANGELOG.md) we keep track of all non-compatible changes that are being [Here](CHANGELOG.md) we keep track of all non-compatible changes that are being made.
made.
## Authentication ## Authentication
If AdGuard Home's web user is password-protected, a web client must use If AdGuard Homes web user is password-protected, a web client must use authentication mechanism when sending requests to server. Basic access authentication is the most simple method: a client must pass `Authorization` HTTP header along with all requests:
authentication mechanism when sending requests to server. Basic access
authentication is the most simple method - a client must pass `Authorization`
HTTP header along with all requests:
```http ```http
Authorization: Basic BASE64_DATA Authorization: Basic BASE64_DATA
``` ```
Where BASE64_DATA is base64-encoded data for `username:password` string. Where `BASE64_DATA` is base64-encoded data for `username:password` string.

View File

@@ -934,6 +934,9 @@
'description': 'OK.' 'description': 'OK.'
'/clients/find': '/clients/find':
'get': 'get':
'deprecated': true
'description': >
Deprecated: Use `POST /clients/search` instead.
'tags': 'tags':
- 'clients' - 'clients'
'operationId': 'clientsFind' 'operationId': 'clientsFind'
@@ -957,6 +960,26 @@
'application/json': 'application/json':
'schema': 'schema':
'$ref': '#/components/schemas/ClientsFindResponse' '$ref': '#/components/schemas/ClientsFindResponse'
'/clients/search':
'post':
'tags':
- 'clients'
'operationId': 'clientsSearch'
'summary': >
Get information about clients by their IP addresses, CIDRs, MAC addresses, or ClientIDs.
'requestBody':
'content':
'application/json':
'schema':
'$ref': '#/components/schemas/ClientsSearchRequest'
'required': true
'responses':
'200':
'description': 'OK.'
'content':
'application/json':
'schema':
'$ref': '#/components/schemas/ClientsFindResponse'
'/access/list': '/access/list':
'get': 'get':
'operationId': 'accessList' 'operationId': 'accessList'
@@ -2478,9 +2501,11 @@
'description': 'Network interface info' 'description': 'Network interface info'
'required': 'required':
- 'flags' - 'flags'
- 'gateway_ip'
- 'hardware_address' - 'hardware_address'
- 'ipv4_addresses'
- 'ipv6_addresses'
- 'name' - 'name'
- 'mtu'
'properties': 'properties':
'flags': 'flags':
'type': 'string' 'type': 'string'
@@ -2489,18 +2514,28 @@
the "|" character: "up", "broadcast", "loopback", "pointtopoint" and the "|" character: "up", "broadcast", "loopback", "pointtopoint" and
"multicast". "multicast".
'example': 'up|broadcast|multicast' 'example': 'up|broadcast|multicast'
'gateway_ip':
'type': 'string'
'description': 'The IP address of the gateway.'
'example': '192.0.2.0'
'hardware_address': 'hardware_address':
'type': 'string' 'type': 'string'
'example': '52:54:00:11:09:ba' 'example': '52:54:00:11:09:ba'
'ipv4_addresses':
'type': 'array'
'description': >
The addresses of the interface of v4 family.
'items':
'type': 'string'
'ipv6_addresses':
'type': 'array'
'description': >
The addresses of the interface of v6 family.
'items':
'type': 'string'
'name': 'name':
'type': 'string' 'type': 'string'
'example': 'eth0' 'example': 'eth0'
'ip_addresses':
'type': 'array'
'items':
'type': 'string'
'mtu':
'type': 'integer'
'AddressInfo': 'AddressInfo':
'type': 'object' 'type': 'object'
'description': 'Port information' 'description': 'Port information'
@@ -2749,6 +2784,20 @@
'properties': 'properties':
'name': 'name':
'type': 'string' 'type': 'string'
'ClientsSearchRequest':
'type': 'object'
'description': 'Client search request'
'properties':
'clients':
'type': 'array'
'items':
'$ref': '#/components/schemas/ClientsSearchRequestItem'
'ClientsSearchRequestItem':
'type': 'object'
'properties':
'id':
'type': 'string'
'description': 'Client IP address, CIDR, MAC address, or ClientID'
'ClientsFindResponse': 'ClientsFindResponse':
'type': 'array' 'type': 'array'
'description': 'Client search results.' 'description': 'Client search results.'

View File

@@ -1,96 +1,72 @@
# AdGuard Home Scripts # AdGuard Home scripts
## `hooks/`: Git Hooks ## `hooks/`: Git hooks
### Usage ### Usage
Run `make init` from the project root. Run `make init` from the project root.
## `querylog/`: Query Log Helpers
### Usage
## `querylog/`: Query Log Helpers - `npm install`: install dependencies. Run this first.
### Usage - `npm run anonymize <source> <dst>`: read the query log from the `<source>` and write anonymized version to `<dst>`.
* `npm install`: install dependencies. Run this first. ## `make/`: Makefile scripts
* `npm run anonymize <source> <dst>`: read the query log from the `<source>`
and write anonymized version to `<dst>`.
The release channels are: `development` (the default), `edge`, `beta`, and `release`. If verbosity levels arent documented here, there are only two: `0`, dont print anything, and `1`, be verbose.
### `build-docker.sh`: Build a multi-architecture Docker image
## `make/`: Makefile scripts
The release channels are: `development` (the default), `edge`, `beta`, and
`release`. If verbosity levels aren't documented here, there are only two: `0`,
don't print anything, and `1`, be verbose.
### `build-docker.sh`: Build a multi-architecture Docker image
Required environment: Required environment:
* `CHANNEL`: release channel, see above. - `CHANNEL`: release channel, see above.
* `DIST_DIR`: the directory where a release has previously been built. - `DIST_DIR`: the directory where a release has previously been built.
* `REVISION`: current Git revision. - `REVISION`: current Git revision.
* `VERSION`: release version. - `VERSION`: release version.
Optional environment: Optional environment:
* `DOCKER_IMAGE_NAME`: the name of the resulting Docker container. By default - `DOCKER_IMAGE_NAME`: the name of the resulting Docker container. By default its `adguardhome-dev`.
it's `adguardhome-dev`.
* `DOCKER_OUTPUT`: the `--output` parameters. By default they are - `DOCKER_OUTPUT`: the `--output` parameters. By default they are `type=image,name=${DOCKER_IMAGE_NAME},push=false`.
`type=image,name=${DOCKER_IMAGE_NAME},push=false`.
* `SUDO`: allow users to use `sudo` or `doas` with `docker`. By default none - `SUDO`: allow users to use `sudo` or `doas` with `docker`. By default none is used.
is used.
### `build-release.sh`: Build a release for all platforms
### `build-release.sh`: Build a release for all platforms
Required environment: Required environment:
* `CHANNEL`: release channel, see above. - `CHANNEL`: release channel, see above.
* `GPG_KEY` and `GPG_KEY_PASSPHRASE`: data for `gpg`. Only required if `SIGN` - `GPG_KEY` and `GPG_KEY_PASSPHRASE`: data for `gpg`. Only required if `SIGN` is `1`.
is `1`.
Optional environment: Optional environment:
* `ARCH` and `OS`: space-separated list of architectures and operating systems - `ARCH` and `OS`: space-separated list of architectures and operating systems for which to build a release. For example, to build only for 64-bit ARM and AMD on Linux and Darwin:
for which to build a release. For example, to build only for 64-bit ARM and
AMD on Linux and Darwin:
```sh ```sh
make ARCH='amd64 arm64' OS='darwin linux' … build-release make ARCH='amd64 arm64' OS='darwin linux' … build-release
``` ```
The default value is `''`, which means build everything. The default value is `''`, which means build everything.
* `DIST_DIR`: the directory to build a release into. The default value is - `DIST_DIR`: the directory to build a release into. The default value is `dist`.
`dist`.
* `GO`: set an alternative name for the Go compiler. - `GO`: set an alternative name for the Go compiler.
* `SIGN`: `0` to not sign the resulting packages, `1` to sign. The default - `SIGN`: `0` to not sign the resulting packages, `1` to sign. The default value is `1`.
value is `1`.
* `VERBOSE`: `1` to be verbose, `2` to also print environment. This script - `VERBOSE`: `1` to be verbose, `2` to also print environment. This script calls `go-build.sh` with the verbosity level one level lower, so to get verbosity level `2` in `go-build.sh`, set this to `3` when calling `build-release.sh`.
calls `go-build.sh` with the verbosity level one level lower, so to get
verbosity level `2` in `go-build.sh`, set this to `3` when calling
`build-release.sh`.
* `VERSION`: release version. Will be set by `version.sh` if it is unset or - `VERSION`: release version. Will be set by `version.sh` if it is unset or if it has the default `Makefile` value of `v0.0.0`.
if it has the default `Makefile` value of `v0.0.0`.
We're using Go's [forward compatibility mechanism][go-toolchain] for updating Were using Gos [forward compatibility mechanism][go-toolchain] for updating the Go version. This means that if your `go` version is 1.21+ but is different from the one required by AdGuard Home, the `go` tool will automatically download the required version.
the Go version. This means that if your `go` version is 1.21+ but is different
from the one required by AdGuard Home, the `go` tool will automatically download
the required version.
If you want to use the version installed on your builder, run: If you want to use the version installed on your builder, run:
@@ -103,220 +79,164 @@ and call `make` with `GOTOOLCHAIN=local`.
[go-toolchain]: https://go.dev/blog/toolchain [go-toolchain]: https://go.dev/blog/toolchain
### `go-bench.sh`: Run backend benchmarks
### `go-bench.sh`: Run backend benchmarks
Optional environment: Optional environment:
* `GO`: set an alternative name for the Go compiler. - `GO`: set an alternative name for the Go compiler.
* `TIMEOUT_FLAGS`: set timeout flags for tests. The default value is - `TIMEOUT_FLAGS`: set timeout flags for tests. The default value is `--timeout=30s`.
`--timeout=30s`.
* `VERBOSE`: verbosity level. `1` shows every command that is run and every - `VERBOSE`: verbosity level. `1` shows every command that is run and every Go package that is processed. `2` also shows subcommands and environment. The default value is `0`, dont be verbose.
Go package that is processed. `2` also shows subcommands and environment.
The default value is `0`, don't be verbose.
### `go-build.sh`: Build the backend
### `go-build.sh`: Build the backend
Optional environment: Optional environment:
* `GOAMD64`: architectural level for [AMD64][amd64]. The default value is - `GOAMD64`: architectural level for [AMD64][amd64]. The default value is `v1`.
`v1`.
* `GOARM`: ARM processor options for the Go compiler. - `GOARM`: ARM processor options for the Go compiler.
* `GOMIPS`: ARM processor options for the Go compiler. - `GOMIPS`: ARM processor options for the Go compiler.
* `GO`: set an alternative name for the Go compiler. - `GO`: set an alternative name for the Go compiler.
* `OUT`: output binary name. - `OUT`: output binary name.
* `PARALLELISM`: set the maximum number of concurrently run build commands - `PARALLELISM`: set the maximum number of concurrently run build commands (that is, compiler, linker, etc.).
(that is, compiler, linker, etc.).
* `SOURCE_DATE_EPOCH`: the [standardized][repr] environment variable for the - `SOURCE_DATE_EPOCH`: the [standardized][repr] environment variable for the Unix epoch time of the latest commit in the repository. If set, overrides the default obtained from Git. Useful for reproducible builds.
Unix epoch time of the latest commit in the repository. If set, overrides
the default obtained from Git. Useful for reproducible builds.
* `VERBOSE`: verbosity level. `1` shows every command that is run and every - `VERBOSE`: verbosity level. `1` shows every command that is run and every Go package that is processed. `2` also shows subcommands and environment. The default value is `0`, dont be verbose.
Go package that is processed. `2` also shows subcommands and environment.
The default value is `0`, don't be verbose.
* `VERSION`: release version. Will be set by `version.sh` if it is unset or - `VERSION`: release version. Will be set by `version.sh` if it is unset or if it has the default `Makefile` value of `v0.0.0`.
if it has the default `Makefile` value of `v0.0.0`.
Required environment: Required environment:
* `CHANNEL`: release channel, see above. - `CHANNEL`: release channel, see above.
[amd64]: https://github.com/golang/go/wiki/MinimumRequirements#amd64 [amd64]: https://github.com/golang/go/wiki/MinimumRequirements#amd64
[repr]: https://reproducible-builds.org/docs/source-date-epoch/ [repr]: https://reproducible-builds.org/docs/source-date-epoch/
### `go-deps.sh`: Install backend dependencies
### `go-deps.sh`: Install backend dependencies
Optional environment: Optional environment:
* `GO`: set an alternative name for the Go compiler. - `GO`: set an alternative name for the Go compiler.
* `VERBOSE`: verbosity level. `1` shows every command that is run and every - `VERBOSE`: verbosity level. `1` shows every command that is run and every Go package that is processed. `2` also shows subcommands and environment. The default value is `0`, dont be verbose.
Go package that is processed. `2` also shows subcommands and environment.
The default value is `0`, don't be verbose.
### `go-fuzz.sh`: Run backend fuzz tests
### `go-fuzz.sh`: Run backend fuzz tests
Optional environment: Optional environment:
* `GO`: set an alternative name for the Go compiler. - `GO`: set an alternative name for the Go compiler.
* `FUZZTIME_FLAGS`: set fuss flags for tests. The default value is - `FUZZTIME_FLAGS`: set fuss flags for tests. The default value is `--fuzztime=20s`.
`--fuzztime=20s`.
* `TIMEOUT_FLAGS`: set timeout flags for tests. The default value is - `TIMEOUT_FLAGS`: set timeout flags for tests. The default value is `--timeout=30s`.
`--timeout=30s`.
* `VERBOSE`: verbosity level. `1` shows every command that is run and every - `VERBOSE`: verbosity level. `1` shows every command that is run and every Go package that is processed. `2` also shows subcommands and environment. The default value is `0`, dont be verbose.
Go package that is processed. `2` also shows subcommands and environment.
The default value is `0`, don't be verbose.
### `go-lint.sh`: Run backend static analyzers
Dont forget to run `make go-tools` once first!
### `go-lint.sh`: Run backend static analyzers
Don't forget to run `make go-tools` once first!
Optional environment: Optional environment:
* `EXIT_ON_ERROR`: if set to `0`, don't exit the script after the first - `EXIT_ON_ERROR`: if set to `0`, dont exit the script after the first encountered error. The default value is `1`.
encountered error. The default value is `1`.
* `GO`: set an alternative name for the Go compiler. - `GO`: set an alternative name for the Go compiler.
* `VERBOSE`: verbosity level. `1` shows every command that is run. `2` also - `VERBOSE`: verbosity level. `1` shows every command that is run. `2` also shows subcommands. The default value is `0`, dont be verbose.
shows subcommands. The default value is `0`, don't be verbose.
### `go-test.sh`: Run backend tests
### `go-test.sh`: Run backend tests
Optional environment: Optional environment:
* `GO`: set an alternative name for the Go compiler. - `GO`: set an alternative name for the Go compiler.
* `RACE`: set to `0` to not use the Go race detector. The default value is - `RACE`: set to `0` to not use the Go race detector. The default value is `1`, use the race detector.
`1`, use the race detector.
* `TIMEOUT_FLAGS`: set timeout flags for tests. The default value is - `TIMEOUT_FLAGS`: set timeout flags for tests. The default value is `--timeout=30s`.
`--timeout=30s`.
* `VERBOSE`: verbosity level. `1` shows every command that is run and every - `VERBOSE`: verbosity level. `1` shows every command that is run and every Go package that is processed. `2` also shows subcommands. The default value is `0`, dont be verbose.
Go package that is processed. `2` also shows subcommands. The default
value is `0`, don't be verbose.
### `go-tools.sh`: Install backend tooling
Installs the Go static analysis and other tools into `${PWD}/bin`. Either add `${PWD}/bin` to your `$PATH` before all other entries, or use the commands directly, or use the commands through `make` (for example, `make go-lint`).
### `go-tools.sh`: Install backend tooling
Installs the Go static analysis and other tools into `${PWD}/bin`. Either add
`${PWD}/bin` to your `$PATH` before all other entries, or use the commands
directly, or use the commands through `make` (for example, `make go-lint`).
Optional environment: Optional environment:
* `GO`: set an alternative name for the Go compiler. - `GO`: set an alternative name for the Go compiler.
### `version.sh`: Generate And Print The Current Version
### `version.sh`: Generate And Print The Current Version
Required environment: Required environment:
* `CHANNEL`: release channel, see above. - `CHANNEL`: release channel, see above.
## `snap/`: Snapcraft scripts
### `build.sh`
## `snap/`: Snapcraft scripts
### `build.sh`
Builds the Snapcraft packages from the binaries created by `download.sh`. Builds the Snapcraft packages from the binaries created by `download.sh`.
### `download.sh` ### `download.sh`
Downloads the binaries to pack them into Snapcraft packages. Downloads the binaries to pack them into Snapcraft packages.
Required environment: Required environment:
* `CHANNEL`: release channel, see above. - `CHANNEL`: release channel, see above.
### `upload.sh` ### `upload.sh`
Uploads the Snapcraft packages created by `build.sh`. Uploads the Snapcraft packages created by `build.sh`.
Required environment: Required environment:
* `SNAPCRAFT_CHANNEL`: Snapcraft release channel: `edge`, `beta`, or - `SNAPCRAFT_CHANNEL`: Snapcraft release channel: `edge`, `beta`, or `candidate`.
`candidate`.
* `SNAPCRAFT_STORE_CREDENTIALS`: Credentials for Snapcraft store. - `SNAPCRAFT_STORE_CREDENTIALS`: Credentials for Snapcraft store.
Optional environment: Optional environment:
* `SNAPCRAFT_CMD`: Overrides the Snapcraft command. Default: `snapcraft`. - `SNAPCRAFT_CMD`: Overrides the Snapcraft command. Default: `snapcraft`.
## `translations/`: Twosky Integration Script
### Usage
## `translations/`: Twosky Integration Script - `go run ./scripts/translations help`: print usage.
### Usage - `go run ./scripts/translations download [-n <count>]`: download and save all translations. `n` is optional flag where count is a number of concurrent downloads.
* `go run ./scripts/translations help`: print usage. - `go run ./scripts/translations upload`: upload the base `en` locale.
* `go run ./scripts/translations download [-n <count>]`: download and save - `go run ./scripts/translations summary`: show the current locales summary.
all translations. `n` is optional flag where count is a number of
concurrent downloads.
* `go run ./scripts/translations upload`: upload the base `en` locale. - `go run ./scripts/translations unused`: show the list of unused strings.
* `go run ./scripts/translations summary`: show the current locales summary. - `go run ./scripts/translations auto-add`: add locales with additions to the git and restore locales with deletions.
* `go run ./scripts/translations unused`: show the list of unused strings. After the download youll find the output locales in the `client/src/__locales/` directory.
* `go run ./scripts/translations auto-add`: add locales with additions to the
git and restore locales with deletions.
After the download you'll find the output locales in the `client/src/__locales/`
directory.
Optional environment: Optional environment:
* `DOWNLOAD_LANGUAGES`: set a list of specific languages to `download`. For - `DOWNLOAD_LANGUAGES`: set a list of specific languages to `download`. For example `ar be bg`. If it set to `blocker` then script will download only those languages, which need to be fully translated (`de en es fr it ja ko pt-br pt-pt ru zh-cn zh-tw`).
example `ar be bg`. If it set to `blocker` then script will download only
those languages, which need to be fully translated (`de en es fr it ja ko
pt-br pt-pt ru zh-cn zh-tw`).
* `UPLOAD_LANGUAGE`: set an alternative language for `upload`. - `UPLOAD_LANGUAGE`: set an alternative language for `upload`.
* `TWOSKY_URI`: set an alternative URL for `download` or `upload`. - `TWOSKY_URI`: set an alternative URL for `download` or `upload`.
* `TWOSKY_PROJECT_ID`: set an alternative project ID for `download` or - `TWOSKY_PROJECT_ID`: set an alternative project ID for `download` or `upload`.
`upload`.
## `companiesdb/`: Whotracks.me database converter
A simple script that downloads and updates the companies DB in the `client` code from [the repo][companiesrepo].
## `companiesdb/`: Whotracks.me Database Converter ### Usage
A simple script that downloads and updates the companies DB in the `client`
code from [the repo][companiesrepo].
### Usage
```sh ```sh
sh ./scripts/companiesdb/download.sh sh ./scripts/companiesdb/download.sh
@@ -324,19 +244,15 @@ sh ./scripts/companiesdb/download.sh
[companiesrepo]: https://github.com/AdguardTeam/companiesdb [companiesrepo]: https://github.com/AdguardTeam/companiesdb
## `blocked-services/`: Blocked-services updater
A simple script that downloads and updates the blocked services index from AdGuards [Hostlists Registry][reg].
## `blocked-services/`: Blocked Services Updater
A simple script that downloads and updates the blocked services index from
AdGuard's [Hostlists Registry][reg].
Optional environment: Optional environment:
* `URL`: the URL of the index file. By default it's - `URL`: the URL of the index file. By default its `https://adguardteam.github.io/HostlistsRegistry/assets/services.json`.
`https://adguardteam.github.io/HostlistsRegistry/assets/services.json`.
### Usage ### Usage
```sh ```sh
go run ./scripts/blocked-services/main.go go run ./scripts/blocked-services/main.go
@@ -344,19 +260,15 @@ go run ./scripts/blocked-services/main.go
[reg]: https://github.com/AdguardTeam/HostlistsRegistry [reg]: https://github.com/AdguardTeam/HostlistsRegistry
## `vetted-filters/`: Vetted-filters updater
Similar to the one above, a script that downloads and updates the vetted filtering list data from AdGuards [Hostlists Registry][reg].
## `vetted-filters/`: Vetted Filters Updater
Similar to the one above, a script that downloads and updates the vetted
filtering list data from AdGuard's [Hostlists Registry][reg].
Optional environment: Optional environment:
* `URL`: the URL of the index file. By default it's - `URL`: the URL of the index file. By default its `https://adguardteam.github.io/HostlistsRegistry/assets/filters.json`.
`https://adguardteam.github.io/HostlistsRegistry/assets/filters.json`.
### Usage ### Usage
```sh ```sh
go run ./scripts/vetted-filters/main.go go run ./scripts/vetted-filters/main.go

View File

@@ -133,7 +133,14 @@ if [ "$verbose" -gt '0' ]; then
"$go" env "$go" env
fi fi
if [ "${COVER:-0}" -eq '1' ]; then
cover_flags='--cover=1'
else
cover_flags='--cover=0'
fi
"$go" build \ "$go" build \
"$cover_flags" \
--ldflags="$ldflags" \ --ldflags="$ldflags" \
"$race_flags" \ "$race_flags" \
"$tags_flags" \ "$tags_flags" \

View File

@@ -223,6 +223,12 @@ run_linter ineffassign ./...
run_linter unparam ./... run_linter unparam ./...
find . \ find . \
'(' \
-name 'node_modules' \
-type 'd' \
-prune \
')' \
-o \
-type 'f' \ -type 'f' \
'(' \ '(' \
-name 'Makefile' \ -name 'Makefile' \

View File

@@ -8,13 +8,21 @@
verbose="${VERBOSE:-0}" verbose="${VERBOSE:-0}"
readonly verbose readonly verbose
set -e -f -u # Don't use -f, because we use globs in this script.
set -e -u
if [ "$verbose" -gt '0' ]; then if [ "$verbose" -gt '0' ]; then
set -x set -x
fi fi
# TODO(e.burkov): Lint markdown documents within this project. # TODO(e.burkov): Add README.md and possibly AGHTechDoc.md.
# markdownlint \ markdownlint \
# ./README.md \ ./CHANGELOG.md \
# ; ./CONTRIBUTING.md \
./HACKING.md \
./SECURITY.md \
./internal/next/changelog.md \
./internal/dhcpd/*.md \
./openapi/*.md \
./scripts/*.md \
;