mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-07-16 17:46:08 +00:00
feat(mtproto): per-client ad-tags, management-API auth, and record secret sync
Catch the panel up to the mtg-multi README (v1.14.0): - Each client can now carry its own 32-hex advertising tag overriding the inbound-level one. The tag lives on the client (settings JSON is the source of truth, clients.ad_tag is the UI projection), is rendered into the fork's [secret-ad-tags] section for active secrets only (mtg rejects a config whose override names an unknown secret), is pushed per entry through PUT /secrets, and is part of the reload fingerprint so a tag edit hot-applies without dropping connections. - The loopback management API can replace the whole secret set, so every mtg process now gets a random per-process api-token; the manager sends it as a bearer token on PUT /secrets and GET /stats and reuses it across config rewrites, because mtg reads the token only at startup. - Malformed tags are rejected at every save path and additionally dropped in InstanceFromInbound: one bad tag would otherwise fail the whole generated config and take every client of the inbound down with it. - SyncInbound never copied a re-keyed mtproto secret into the canonical clients table, so the clients page and subscription links kept serving the old secret, which mtg then rejects. It is now guarded-copied like the other credentials.
This commit is contained in:
@@ -30,6 +30,10 @@ func TestScrapeStats(t *testing.T) {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
if r.Header.Get("Authorization") != "Bearer sesame" {
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
_, _ = io.WriteString(w, `{"started_at":"2026-01-01T00:00:00Z","total_connections":2,`+
|
||||
`"users":{`+
|
||||
`"alice":{"connections":2,"bytes_in":100,"bytes_out":200,"last_seen":"2026-01-01T00:01:00Z"},`+
|
||||
@@ -37,7 +41,7 @@ func TestScrapeStats(t *testing.T) {
|
||||
}))
|
||||
defer srv.Close()
|
||||
|
||||
users, ok := scrapeStats(serverPort(t, srv))
|
||||
users, ok := scrapeStats(serverPort(t, srv), "sesame")
|
||||
if !ok {
|
||||
t.Fatal("scrapeStats should succeed against a valid /stats endpoint")
|
||||
}
|
||||
@@ -59,7 +63,7 @@ func TestScrapeStatsUnreachable(t *testing.T) {
|
||||
port := serverPort(t, srv)
|
||||
srv.Close()
|
||||
|
||||
if _, ok := scrapeStats(port); ok {
|
||||
if _, ok := scrapeStats(port, ""); ok {
|
||||
t.Fatal("scrapeStats must report ok=false when the endpoint is unreachable")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user