Files
meshcore-analyzer/cmd/server/client_config_linked_test.go
T
efitenandClaude Opus 5.5 c370678f4b feat(observer-logins): account endpoints and credentials mail
GET/POST /api/account/observer-login and POST .../resend, gated on
userManagement.observerLogins. The password is hashed for the broker and
sealed for resend; it only leaves the server in the credentials mail
(three pre blocks: meshcoretomqtt, Dutch-MeshCore firmware, plain).
Resend is limited to 3 credential mails per 24 h (mail_log count).
The account export gains the login metadata and bindings, never the
credential material. /api/config/client announces observerLogins.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 15:55:27 +01:00

90 lines
3.0 KiB
Go

package main
import (
"bytes"
"log"
"net/http/httptest"
"os"
"path/filepath"
"strings"
"testing"
)
func TestClientConfigRequireLinkedCompanion(t *testing.T) {
srv, router := setupTestServer(t)
get := func() string {
w := httptest.NewRecorder()
router.ServeHTTP(w, httptest.NewRequest("GET", "/api/config/client", nil))
return w.Body.String()
}
if strings.Contains(get(), "clientRxRequireLinkedCompanion") {
t.Fatal("field present by default")
}
srv.cfg.ClientRxCoverage = &ClientRxCoverageConfig{Enabled: true, RequireLinkedCompanion: true}
if strings.Contains(get(), "clientRxRequireLinkedCompanion") {
t.Fatal("field present without user management")
}
a, _ := newTestAuthService(t)
srv.auth = a
if !strings.Contains(get(), `"clientRxRequireLinkedCompanion":true`) {
t.Fatalf("field missing with user management on: %s", get())
}
srv.cfg.ClientRxCoverage.RequireLinkedCompanion = false
if strings.Contains(get(), "clientRxRequireLinkedCompanion") {
t.Fatal("field present with the setting off")
}
}
func TestRequireLinkedCompanionWarnsWithoutUserManagement(t *testing.T) {
var buf bytes.Buffer
log.SetOutput(&buf)
t.Cleanup(func() { log.SetOutput(os.Stderr) })
srv := &Server{cfg: &Config{ClientRxCoverage: &ClientRxCoverageConfig{Enabled: true, RequireLinkedCompanion: true}}}
if err := srv.initUserManagement(filepath.Join(t.TempDir(), "meshcore.db")); err != nil || srv.auth != nil {
t.Fatalf("initUserManagement: auth=%v err=%v", srv.auth, err)
}
if !strings.Contains(buf.String(), "requireLinkedCompanion") {
t.Fatalf("no startup warning, log: %q", buf.String())
}
}
// CoreDrive RX shows its login only when the server says it supports companion
// linking: a CoreScope with user management but without these routes answers the
// device-token POST with the SPA page.
func TestClientConfigAnnouncesCompanionLinking(t *testing.T) {
srv, router := setupTestServer(t)
get := func() string {
w := httptest.NewRecorder()
router.ServeHTTP(w, httptest.NewRequest("GET", "/api/config/client", nil))
return w.Body.String()
}
if strings.Contains(get(), "companionLinking") {
t.Fatal("companionLinking present with user management off")
}
a, _ := newTestAuthService(t)
srv.auth = a
if !strings.Contains(get(), `"companionLinking":true`) {
t.Fatalf("companionLinking missing with user management on: %s", get())
}
}
// The account page shows the observer-login section only when the server
// has the routes.
func TestClientConfigAnnouncesObserverLogins(t *testing.T) {
srv, router := setupTestServer(t)
get := func() string {
w := httptest.NewRecorder()
router.ServeHTTP(w, httptest.NewRequest("GET", "/api/config/client", nil))
return w.Body.String()
}
a, _ := newTestAuthService(t)
srv.auth = a
if strings.Contains(get(), "observerLogins") {
t.Fatal("observerLogins present with the feature off")
}
a.set.observerLogins.enabled = true
if !strings.Contains(get(), `"observerLogins":true`) {
t.Fatalf("observerLogins missing with the feature on: %s", get())
}
}