Оба места утверждали, что у Домклика один выделенный резидентный прокси и пула нет. Это перестало быть правдой ещё в #2800 (миграция 253 сняла резервацию узла), но текст остался — и именно на него опирался тикет #3189, поставленный под «калибровку» ограничения, которого не существует. Свип к тому же ходит через пул давно (serp.py:359), а бэкфилл подключён к нему в PR #3222. Заодно докстринг называл не тот ограничитель: свип кладёт не счётчик провалов lease, а break по первому DomClickBlockedError (#2854) — до ротации дело не доходит ни при каком счётчике, отсюда buckets_completed=0. Только комментарии, поведение не меняется. Миграция 175 уже применена, а _schema_migrations трекает по имени файла без checksum — правка текста её не перезапустит.
65 lines
2.6 KiB
Bash
65 lines
2.6 KiB
Bash
#!/usr/bin/env bash
|
||
# list_users.sh — показать текущих пользователей (имена + comment, без хешей)
|
||
# Usage: ./scripts/auth/list_users.sh
|
||
set -euo pipefail
|
||
|
||
# 3× dirname от $0 (.../scripts/auth/list_users.sh) → repo root. Bug fix 2026-05-26.
|
||
SCRIPT_DIR="$(cd "$(dirname "$(realpath "$0")")" && pwd)"
|
||
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||
SNIPPET="$REPO_ROOT/caddy/users.caddy.snippet"
|
||
|
||
if [[ ! -f "$SNIPPET" ]]; then
|
||
echo "ERROR: snippet not found at $SNIPPET" >&2
|
||
exit 1
|
||
fi
|
||
|
||
echo "Users in $SNIPPET:"
|
||
echo ""
|
||
printf "%-12s %s\n" "USERNAME" "COMMENT"
|
||
printf "%-12s %s\n" "--------" "-------"
|
||
|
||
# Parse only the real user lines INSIDE the `basic_auth ... { ... }` block (#429).
|
||
# The previous grep `^\s+[a-z][a-z0-9-]+\s+[A-Za-z0-9+/]+=*` also matched indented
|
||
# base64-ish comment text and miscounted. Here we:
|
||
# - enter the block on a line whose first token is `basic_auth` ending in `{`;
|
||
# - leave it on the closing `}`;
|
||
# - inside, skip blank and comment-only lines, require a username-shaped first
|
||
# field (^[a-z][a-z0-9_.-]+$, matches add/remove_user.sh) AND a 2nd field
|
||
# (the hash). Comment is whatever follows the first `#`.
|
||
# A single pass prints rows and the total, so the count can't drift from the list.
|
||
awk '
|
||
$1 == "basic_auth" && /\{[[:space:]]*$/ { in_block = 1; next }
|
||
in_block && /^[[:space:]]*\}/ { in_block = 0; next }
|
||
!in_block { next }
|
||
|
||
{
|
||
line = $0
|
||
sub(/^[[:space:]]+/, "", line) # strip leading indent
|
||
if (line == "" || line ~ /^#/) next # blank / comment-only
|
||
|
||
user = line
|
||
sub(/[[:space:]].*$/, "", user) # first whitespace-delimited token
|
||
if (user !~ /^[a-z][a-z0-9_.-]+$/) next # must look like a username
|
||
|
||
rest = line
|
||
sub(/^[^[:space:]]+[[:space:]]+/, "", rest) # drop username
|
||
if (rest == "") next # no 2nd field -> not a user line
|
||
|
||
hash = rest
|
||
sub(/[[:space:]].*$/, "", hash) # 2nd token = the hash
|
||
# Real entry: 2nd token is a base64-encoded bcrypt hash (base64 charset,
|
||
# long). This is what excludes indented prose like "note this ..." whose
|
||
# 2nd word ("this") is short non-base64 text — the #429 false positive.
|
||
if (hash !~ /^[A-Za-z0-9+\/=]{20,}$/) next
|
||
|
||
comment = ""
|
||
h = index(rest, "#")
|
||
if (h > 0) {
|
||
comment = substr(rest, h + 1)
|
||
sub(/^[[:space:]]+/, "", comment)
|
||
}
|
||
printf "%-12s %s\n", user, comment
|
||
count++
|
||
}
|
||
END { print ""; printf "Total: %d user(s)\n", count }
|
||
' "$SNIPPET"
|