From 4522797a0cf378cc44485ed77a01dee9643b6ebe Mon Sep 17 00:00:00 2001 From: bndw Date: Sat, 7 Mar 2026 18:34:25 -0800 Subject: Make allowed event kinds configurable Replaces hardcoded kind allowlist in isAllowedKind with a configurable allowed_kinds list in relay config. Empty list allows all kinds. Default matches previous hardcoded list. Wired through SetAllowedKinds on the handler. --- internal/handler/websocket/handler.go | 68 ++++++++++++++--------------------- 1 file changed, 27 insertions(+), 41 deletions(-) (limited to 'internal/handler/websocket/handler.go') diff --git a/internal/handler/websocket/handler.go b/internal/handler/websocket/handler.go index b11171d..c64f3f9 100644 --- a/internal/handler/websocket/handler.go +++ b/internal/handler/websocket/handler.go @@ -64,14 +64,15 @@ type connState struct { } type Handler struct { - store EventStore - auth AuthStore - subs *subscription.Manager - metrics MetricsRecorder - limiter RateLimiter - authConfig *AuthConfig - relayConfig *RelayInfoConfig - indexData IndexData + store EventStore + auth AuthStore + subs *subscription.Manager + metrics MetricsRecorder + limiter RateLimiter + authConfig *AuthConfig + relayConfig *RelayInfoConfig + indexData IndexData + allowedKinds map[int32]bool // nil = allow all } func NewHandler(store EventStore, subs *subscription.Manager) *Handler { @@ -81,6 +82,17 @@ func NewHandler(store EventStore, subs *subscription.Manager) *Handler { } } +func (h *Handler) SetAllowedKinds(kinds []int32) { + if len(kinds) == 0 { + h.allowedKinds = nil // nil = allow all + return + } + h.allowedKinds = make(map[int32]bool, len(kinds)) + for _, k := range kinds { + h.allowedKinds[k] = true + } +} + func (h *Handler) SetMetrics(m MetricsRecorder) { h.metrics = m } @@ -325,8 +337,8 @@ func (h *Handler) handleEvent(ctx context.Context, conn *websocket.Conn, raw []j pbEvent := NostrToPB(&event) canonicalJSON := event.Serialize() - // Reject non-core protocol kinds (spam, ephemeral, chat) - if !isAllowedKind(pbEvent.Kind) { + // Reject kinds not in the allowed list + if !h.isAllowedKind(pbEvent.Kind) { status = "ok" if h.metrics != nil { h.metrics.RecordBlockedEvent(pbEvent.Kind) @@ -623,37 +635,11 @@ func getClientIP(r *http.Request) string { return r.RemoteAddr } -// isAllowedKind returns true if the event kind is a core Nostr protocol kind. -// Rejects spam, ephemeral events, live chat, and other non-essential kinds. -func isAllowedKind(kind int32) bool { - // Core protocol kinds (NIP-01, NIP-02, etc.) - switch kind { - case 0: // Metadata/profile - return true - case 1: // Short text note - return true - case 3: // Contacts/following - return true - case 4: // Encrypted DM - return true - case 5: // Event deletion (handled separately) +// isAllowedKind returns true if the event kind is permitted by the relay config. +// If no allowed kinds are configured, all kinds are accepted. +func (h *Handler) isAllowedKind(kind int32) bool { + if h.allowedKinds == nil { return true - case 6: // Repost - return true - case 7: // Reaction - return true - case 9735: // Zap - return true - case 10000, 10001, 10002: // Mute lists, pin lists (NIP-51) - return true - case 10050: // Relay list metadata - return true - case 30023: // Long-form content (NIP-23) - return true - case 30078: // Application-specific data (NIP-78) - return true - default: - // Reject everything else (chat, ephemeral, spam) - return false } + return h.allowedKinds[kind] } -- cgit v1.2.3