Master keys: a down server no longer breaks the device list, 403 for keys outside the API key's scope
masterDevices skips a server that did not answer and reports it as unreachable; peers are fetched once per server per pass. The tab loads each key on its own, counts devices from the key when the list is missing (and still asks before unbinding), drops stale responses, labels an IP from another server and blocks a double create. masterFor answers 403 instead of 404 for a key that exists but is outside the API key's servers, so a client does not mistake it for a deleted one. updateMaster checks every statement in its transaction.
This commit is contained in:
+9
-5
@@ -186,6 +186,9 @@ type Sub struct {
|
||||
locksMu sync.Mutex
|
||||
locks map[int]*sync.Mutex // один проход на сервер за раз
|
||||
|
||||
peersMu sync.Mutex
|
||||
peerCalls map[int]*peersCall // последний GET /api/peers по серверу, см. peersOf
|
||||
|
||||
sigMu sync.Mutex
|
||||
seenSigs map[string]time.Time // подпись → когда забыть
|
||||
|
||||
@@ -201,11 +204,12 @@ type Sub struct {
|
||||
func newSub(a *App) (*Sub, error) {
|
||||
s := &Sub{
|
||||
a: a, port: envNum("SUB_PORT"),
|
||||
useTLS: strings.ToLower(envOr("SUB_TLS", "off")) == "on",
|
||||
host: strings.TrimSpace(os.Getenv("SUB_HOST")),
|
||||
auditOn: strings.ToLower(envOr("AUDIT", "on")) != "off",
|
||||
locks: map[int]*sync.Mutex{},
|
||||
seenSigs: map[string]time.Time{},
|
||||
useTLS: strings.ToLower(envOr("SUB_TLS", "off")) == "on",
|
||||
host: strings.TrimSpace(os.Getenv("SUB_HOST")),
|
||||
auditOn: strings.ToLower(envOr("AUDIT", "on")) != "off",
|
||||
locks: map[int]*sync.Mutex{},
|
||||
peerCalls: map[int]*peersCall{},
|
||||
seenSigs: map[string]time.Time{},
|
||||
}
|
||||
limited := func(what string) func(string) {
|
||||
return func(ip string) {
|
||||
|
||||
Reference in New Issue
Block a user