mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-08-31 07:27:13 +00:00
fix(xray): guard RemoveUser against an uninitialized handler client
Every XrayAPI handler method returns an error when HandlerServiceClient is nil, except RemoveUser, which dereferenced it directly. A depletion sweep runs Init with the port ignored and, during a restart window where the fresh process's api port is still 0, Init fails and leaves the client nil — so RemoveUser panicked (recovered by the traffic writer, but re-thrown every poll) instead of returning an error. Add the same nil guard the siblings have.
This commit is contained in:
@@ -637,6 +637,11 @@ func (x *XrayAPI) AddUser(Protocol string, inboundTag string, user map[string]an
|
|||||||
|
|
||||||
// RemoveUser removes a user from an inbound in the Xray core by email.
|
// RemoveUser removes a user from an inbound in the Xray core by email.
|
||||||
func (x *XrayAPI) RemoveUser(inboundTag, email string) error {
|
func (x *XrayAPI) RemoveUser(inboundTag, email string) error {
|
||||||
|
if x.HandlerServiceClient == nil {
|
||||||
|
return common.NewError("xray HandlerServiceClient is not initialized")
|
||||||
|
}
|
||||||
|
client := *x.HandlerServiceClient
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
@@ -646,7 +651,7 @@ func (x *XrayAPI) RemoveUser(inboundTag, email string) error {
|
|||||||
Operation: serial.ToTypedMessage(op),
|
Operation: serial.ToTypedMessage(op),
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := (*x.HandlerServiceClient).AlterInbound(ctx, req)
|
_, err := client.AlterInbound(ctx, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to remove user: %w", err)
|
return fmt.Errorf("failed to remove user: %w", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,16 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// RemoveUser must return an error, not panic, when the handler client is not
|
||||||
|
// initialized — matching every sibling API method. A depletion sweep can reach
|
||||||
|
// it with a nil client during a restart window where Init(0) failed.
|
||||||
|
func TestRemoveUserGuardsNilHandlerClient(t *testing.T) {
|
||||||
|
err := (&XrayAPI{}).RemoveUser("in-443-tcp", "user@example.com")
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("RemoveUser with an uninitialized HandlerServiceClient must return an error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestGetRequiredUserString_Present(t *testing.T) {
|
func TestGetRequiredUserString_Present(t *testing.T) {
|
||||||
user := map[string]any{"email": "alice@example.com"}
|
user := map[string]any{"email": "alice@example.com"}
|
||||||
got, err := getRequiredUserString(user, "email")
|
got, err := getRequiredUserString(user, "email")
|
||||||
|
|||||||
Reference in New Issue
Block a user