Files

123 lines
3.2 KiB
Go

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
}