package accept import ( "bytes" "encoding/json" "fmt" "io" "net/http" "testing" "time" "git.asio.asia/nixevol/NixMsg/test/harness" "github.com/mochi-mqtt/server/v2/packets" ) // AdminLogin 管理登录并返回带 Cookie/CSRF 的客户端。 func AdminLogin(t *testing.T, srv *harness.Server) *harness.AdminClient { t.Helper() ac, err := srv.AdminClient() if err != nil { t.Fatal(err) } loginBody, _ := json.Marshal(map[string]string{ "username": "admin", "password": srv.AdminPassword, }) lr, err := ac.PostJSON("/api/admin/login", loginBody) if err != nil { t.Fatal(err) } raw, _ := io.ReadAll(lr.Body) _ = lr.Body.Close() if lr.StatusCode != http.StatusOK { t.Fatalf("admin login: %d %s", lr.StatusCode, raw) } return ac } // CreateEndpoint 用管理接口开通一端。 func CreateEndpoint(t *testing.T, ac *harness.AdminClient, id, password string) { t.Helper() body, _ := json.Marshal(map[string]string{ "id": id, "login_password": password, }) resp, err := ac.PostJSON("/api/admin/endpoints", body) if err != nil { t.Fatal(err) } raw, _ := io.ReadAll(resp.Body) _ = resp.Body.Close() if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusCreated { t.Fatalf("create endpoint %s: %d %s", id, resp.StatusCode, raw) } } // EnableRegistration 管理接口开启注册并设置安全码。 func EnableRegistration(t *testing.T, ac *harness.AdminClient, code string) { t.Helper() body := fmt.Sprintf(`{"enabled":true,"code":%q}`, code) resp, err := ac.Do(http.MethodPut, "/api/admin/registration", []byte(body), "application/json") if err != nil { t.Fatal(err) } raw, _ := io.ReadAll(resp.Body) _ = resp.Body.Close() if resp.StatusCode != http.StatusOK { t.Fatalf("enable registration: %d %s", resp.StatusCode, raw) } } // RegisterClient 调用端注册接口。 func RegisterClient(t *testing.T, httpBase, regCode, id, password string) (status int, body string) { t.Helper() payload := fmt.Sprintf(`{"registration_code":%q,"id":%q,"login_password":%q}`, regCode, id, password) code, text, err := ProbeMethod(httpBase, http.MethodPost, "/api/client/register", []byte(payload)) if err != nil { t.Fatal(err) } return code, text } // TryMQTTPasswordLogin 尝试密码登录;CONNACK 成功返回 true。 func TryMQTTPasswordLogin(t *testing.T, httpBase, endpointID, password string) bool { t.Helper() mc, err := harness.DialMQTTWebSocket(httpBase, 5*time.Second) if err != nil { t.Logf("dial: %v", err) return false } defer func() { _ = mc.Close() }() pk := packets.Packet{ FixedHeader: packets.FixedHeader{Type: packets.Connect}, ProtocolVersion: 5, Connect: packets.ConnectParams{ ProtocolName: []byte("MQTT"), Clean: true, ClientIdentifier: endpointID, Keepalive: 30, UsernameFlag: true, Username: []byte(endpointID), PasswordFlag: true, Password: []byte(password), }, } var buf bytes.Buffer if encErr := pk.ConnectEncode(&buf); encErr != nil { t.Fatal(encErr) } if sendErr := mc.Send(buf.Bytes()); sendErr != nil { return false } ack, recvErr := mc.Recv() if recvErr != nil { return false } if len(ack) < 4 || ack[0]>>4 != packets.Connack { return false } return ack[3] == 0 }