mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-07-10 00:14:38 +00:00
255 lines
8.8 KiB
Go
255 lines
8.8 KiB
Go
package api
|
|
|
|
import (
|
|
"context"
|
|
"crypto/ed25519"
|
|
"encoding/base64"
|
|
"net/http/httptest"
|
|
"net/url"
|
|
"testing"
|
|
|
|
"github.com/rcourtman/pulse-go-rewrite/internal/config"
|
|
"github.com/rcourtman/pulse-go-rewrite/internal/relay"
|
|
pkglicensing "github.com/rcourtman/pulse-go-rewrite/pkg/licensing"
|
|
)
|
|
|
|
func TestLoadRelayConfigForRuntime_HostedEntitlementAutoBootstrapsRelay(t *testing.T) {
|
|
router, entitlementJWT, instanceHost := newHostedRelayRuntimeTestRouter(t)
|
|
|
|
cfg, err := router.loadRelayConfigForRuntime(context.Background())
|
|
if err != nil {
|
|
t.Fatalf("loadRelayConfigForRuntime() error = %v", err)
|
|
}
|
|
if cfg == nil {
|
|
t.Fatal("loadRelayConfigForRuntime() returned nil config")
|
|
}
|
|
if !cfg.Enabled {
|
|
t.Fatal("expected hosted relay bootstrap to enable relay")
|
|
}
|
|
if cfg.ServerURL != relay.DefaultServerURL {
|
|
t.Fatalf("server_url = %q, want %q", cfg.ServerURL, relay.DefaultServerURL)
|
|
}
|
|
if cfg.InstanceSecret != instanceHost {
|
|
t.Fatalf("instance_secret = %q, want %q", cfg.InstanceSecret, instanceHost)
|
|
}
|
|
if cfg.IdentityPrivateKey == "" || cfg.IdentityPublicKey == "" || cfg.IdentityFingerprint == "" {
|
|
t.Fatalf("expected hosted relay bootstrap to generate full identity, got %+v", cfg)
|
|
}
|
|
|
|
persisted, err := router.persistence.LoadRelayConfig()
|
|
if err != nil {
|
|
t.Fatalf("LoadRelayConfig() error = %v", err)
|
|
}
|
|
if persisted == nil || !persisted.Enabled {
|
|
t.Fatal("expected persisted hosted relay config to be enabled")
|
|
}
|
|
if persisted.InstanceSecret != instanceHost {
|
|
t.Fatalf("persisted instance_secret = %q, want %q", persisted.InstanceSecret, instanceHost)
|
|
}
|
|
|
|
gotToken := router.relayRegistrationToken(context.Background())
|
|
if gotToken != entitlementJWT {
|
|
t.Fatalf("relayRegistrationToken() = %q, want hosted entitlement JWT", gotToken)
|
|
}
|
|
}
|
|
|
|
func TestLoadRelayConfigForRuntime_EnvEnabledRelayGeneratesPersistedIdentity(t *testing.T) {
|
|
t.Setenv(relay.EnvRelayEnabled, "true")
|
|
t.Setenv(relay.EnvRelayServerURL, "wss://relay.internal.example/ws/instance")
|
|
|
|
persistence := config.NewConfigPersistence(t.TempDir())
|
|
router := &Router{persistence: persistence}
|
|
|
|
cfg, err := router.loadRelayConfigForRuntime(context.Background())
|
|
if err != nil {
|
|
t.Fatalf("loadRelayConfigForRuntime() error = %v", err)
|
|
}
|
|
if cfg == nil {
|
|
t.Fatal("loadRelayConfigForRuntime() returned nil config")
|
|
}
|
|
if !cfg.Enabled {
|
|
t.Fatal("expected env-enabled relay config to remain enabled")
|
|
}
|
|
if cfg.ServerURL != "wss://relay.internal.example/ws/instance" {
|
|
t.Fatalf("server_url = %q, want env override", cfg.ServerURL)
|
|
}
|
|
if cfg.IdentityPrivateKey == "" || cfg.IdentityPublicKey == "" || cfg.IdentityFingerprint == "" {
|
|
t.Fatal("expected env-enabled relay config to generate full identity")
|
|
}
|
|
|
|
t.Setenv(relay.EnvRelayEnabled, "")
|
|
t.Setenv(relay.EnvRelayServerURL, "")
|
|
|
|
persisted, err := persistence.LoadRelayConfig()
|
|
if err != nil {
|
|
t.Fatalf("LoadRelayConfig() error = %v", err)
|
|
}
|
|
if persisted == nil || !persisted.Enabled {
|
|
t.Fatal("expected generated relay identity config to be persisted enabled")
|
|
}
|
|
if persisted.ServerURL != cfg.ServerURL {
|
|
t.Fatalf("persisted server_url = %q, want %q", persisted.ServerURL, cfg.ServerURL)
|
|
}
|
|
if persisted.IdentityPrivateKey == "" || persisted.IdentityPublicKey == "" || persisted.IdentityFingerprint == "" {
|
|
t.Fatal("expected persisted relay config to include full identity")
|
|
}
|
|
}
|
|
|
|
func TestLoadRelayConfigForRuntime_EnabledPartialIdentityRegeneratesFullIdentity(t *testing.T) {
|
|
persistence := config.NewConfigPersistence(t.TempDir())
|
|
partial := relay.Config{
|
|
Enabled: true,
|
|
ServerURL: "wss://relay.example.test/ws/instance",
|
|
InstanceSecret: "relay-instance-secret",
|
|
IdentityPrivateKey: "private-key-without-public-material",
|
|
}
|
|
if err := persistence.SaveRelayConfig(partial); err != nil {
|
|
t.Fatalf("SaveRelayConfig() error = %v", err)
|
|
}
|
|
|
|
router := &Router{persistence: persistence}
|
|
cfg, err := router.loadRelayConfigForRuntime(context.Background())
|
|
if err != nil {
|
|
t.Fatalf("loadRelayConfigForRuntime() error = %v", err)
|
|
}
|
|
if cfg == nil {
|
|
t.Fatal("loadRelayConfigForRuntime() returned nil config")
|
|
}
|
|
if !cfg.Enabled {
|
|
t.Fatal("expected enabled relay config to remain enabled")
|
|
}
|
|
if cfg.IdentityPrivateKey == partial.IdentityPrivateKey {
|
|
t.Fatal("expected partial relay identity to be replaced with a complete keypair")
|
|
}
|
|
if cfg.IdentityPrivateKey == "" || cfg.IdentityPublicKey == "" || cfg.IdentityFingerprint == "" {
|
|
t.Fatal("expected enabled relay config to include full identity")
|
|
}
|
|
|
|
persisted, err := persistence.LoadRelayConfig()
|
|
if err != nil {
|
|
t.Fatalf("LoadRelayConfig() error = %v", err)
|
|
}
|
|
if persisted == nil || persisted.IdentityPrivateKey != cfg.IdentityPrivateKey {
|
|
t.Fatal("expected repaired relay identity to be persisted")
|
|
}
|
|
if persisted.IdentityPublicKey == "" || persisted.IdentityFingerprint == "" {
|
|
t.Fatal("expected persisted relay identity to be complete")
|
|
}
|
|
}
|
|
|
|
func TestLoadRelayConfigForRuntime_DoesNotOverrideExplicitDisabledRelayConfig(t *testing.T) {
|
|
router, _, instanceHost := newHostedRelayRuntimeTestRouter(t)
|
|
|
|
explicit := relay.Config{
|
|
Enabled: false,
|
|
ServerURL: "wss://relay.example.test/ws/instance",
|
|
InstanceSecret: "user-managed-secret",
|
|
IdentityPrivateKey: "user-private",
|
|
IdentityPublicKey: "user-public",
|
|
IdentityFingerprint: "USER:FP",
|
|
}
|
|
if err := router.persistence.SaveRelayConfig(explicit); err != nil {
|
|
t.Fatalf("SaveRelayConfig() error = %v", err)
|
|
}
|
|
|
|
cfg, err := router.loadRelayConfigForRuntime(context.Background())
|
|
if err != nil {
|
|
t.Fatalf("loadRelayConfigForRuntime() error = %v", err)
|
|
}
|
|
if cfg.Enabled {
|
|
t.Fatal("expected explicit disabled relay config to remain disabled")
|
|
}
|
|
if cfg.InstanceSecret != explicit.InstanceSecret {
|
|
t.Fatalf("instance_secret = %q, want %q", cfg.InstanceSecret, explicit.InstanceSecret)
|
|
}
|
|
if cfg.InstanceSecret == instanceHost {
|
|
t.Fatalf("expected explicit config to avoid hosted auto-bootstrap secret %q", instanceHost)
|
|
}
|
|
}
|
|
|
|
func TestHostedRelayRuntimeBuildsMobileOnboardingAppRelayURL(t *testing.T) {
|
|
router, _, instanceHost := newHostedRelayRuntimeTestRouter(t)
|
|
|
|
relayCfg, err := router.loadRelayConfigForRuntime(context.Background())
|
|
if err != nil {
|
|
t.Fatalf("loadRelayConfigForRuntime() error = %v", err)
|
|
}
|
|
router.relayClient = fakeRelayRuntimeClient{
|
|
status: relay.ClientStatus{
|
|
Connected: true,
|
|
InstanceID: instanceHost,
|
|
},
|
|
}
|
|
|
|
req := httptest.NewRequest("GET", "https://t-hostedrelay01.cloud.pulserelay.pro/api/onboarding/qr", nil)
|
|
payload, diagnostics := router.buildOnboardingPayload(req, relayCfg, "test-mobile-proof-token")
|
|
if hasOnboardingError(diagnostics) {
|
|
t.Fatalf("onboarding diagnostics contain errors: %#v", diagnostics)
|
|
}
|
|
if payload.Relay.URL != "wss://relay.pulserelay.pro/ws/app" {
|
|
t.Fatalf("mobile onboarding relay URL = %q", payload.Relay.URL)
|
|
}
|
|
|
|
deepLink, err := url.Parse(payload.DeepLink)
|
|
if err != nil {
|
|
t.Fatalf("parse deep link: %v", err)
|
|
}
|
|
query := deepLink.Query()
|
|
if query.Get("relay_url") != payload.Relay.URL {
|
|
t.Fatalf("deep-link relay_url = %q, want %q", query.Get("relay_url"), payload.Relay.URL)
|
|
}
|
|
if query.Get("auth_token") != "test-mobile-proof-token" {
|
|
t.Fatalf("deep-link auth_token did not preserve the proof token")
|
|
}
|
|
}
|
|
|
|
func newHostedRelayRuntimeTestRouter(t *testing.T) (*Router, string, string) {
|
|
t.Helper()
|
|
|
|
pub, priv, err := ed25519.GenerateKey(nil)
|
|
if err != nil {
|
|
t.Fatalf("generate entitlement keypair: %v", err)
|
|
}
|
|
t.Setenv(pkglicensing.TrialActivationPublicKeyEnvVar, base64.StdEncoding.EncodeToString(pub))
|
|
|
|
baseDir := t.TempDir()
|
|
cfg := &config.Config{
|
|
DataPath: baseDir,
|
|
FrontendPort: 7655,
|
|
PublicURL: "https://t-HOSTEDRELAY01.cloud.pulserelay.pro",
|
|
}
|
|
mtp := config.NewMultiTenantPersistence(baseDir)
|
|
persistence, err := mtp.GetPersistence(hostedRelayBootstrapOrgID)
|
|
if err != nil {
|
|
t.Fatalf("GetPersistence(default) error = %v", err)
|
|
}
|
|
|
|
instanceHost := "t-hostedrelay01.cloud.pulserelay.pro"
|
|
entitlementJWT, err := pkglicensing.SignEntitlementLeaseToken(priv, pkglicensing.EntitlementLeaseClaims{
|
|
OrgID: hostedRelayBootstrapOrgID,
|
|
InstanceHost: instanceHost,
|
|
PlanVersion: "cloud",
|
|
SubscriptionState: pkglicensing.SubStateActive,
|
|
Capabilities: []string{pkglicensing.FeatureRelay},
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("SignEntitlementLeaseToken() error = %v", err)
|
|
}
|
|
|
|
billingStore := config.NewFileBillingStore(mtp.BaseDataDir())
|
|
if err := billingStore.SaveBillingState(hostedRelayBootstrapOrgID, &billingState{
|
|
PlanVersion: "cloud",
|
|
SubscriptionState: subscriptionStateActiveValue,
|
|
Capabilities: []string{pkglicensing.FeatureRelay},
|
|
EntitlementJWT: entitlementJWT,
|
|
}); err != nil {
|
|
t.Fatalf("SaveBillingState() error = %v", err)
|
|
}
|
|
|
|
router := &Router{
|
|
config: cfg,
|
|
persistence: persistence,
|
|
licenseHandlers: NewLicenseHandlers(mtp, true, cfg),
|
|
}
|
|
return router, entitlementJWT, instanceHost
|
|
}
|