From 4f721f04b7b5f6746e4509bb47d0a023b164d404 Mon Sep 17 00:00:00 2001 From: Cody Tseng <64680921+CodyTseng@users.noreply.github.com> Date: Sat, 3 Feb 2024 23:02:32 +0800 Subject: [PATCH] fix(core): resolve bug in broadcasting encrypted messages (#12) --- .../__test__/services/event.service.spec.ts | 1 + .../services/subscription.service.spec.ts | 39 +++++++++++++++++++ packages/core/src/nostr-relay.ts | 1 + .../core/src/services/subscription.service.ts | 10 +++-- 4 files changed, 48 insertions(+), 3 deletions(-) diff --git a/packages/core/__test__/services/event.service.spec.ts b/packages/core/__test__/services/event.service.spec.ts index 599ade7c..17fafb8e 100644 --- a/packages/core/__test__/services/event.service.spec.ts +++ b/packages/core/__test__/services/event.service.spec.ts @@ -29,6 +29,7 @@ describe('eventService', () => { subscriptionService = new SubscriptionService( new Map(), new ConsoleLoggerService(), + true, ); subscriptionService.broadcast = jest.fn(); pluginManagerService = new PluginManagerService(); diff --git a/packages/core/__test__/services/subscription.service.spec.ts b/packages/core/__test__/services/subscription.service.spec.ts index 259a1ed0..56cd51be 100644 --- a/packages/core/__test__/services/subscription.service.spec.ts +++ b/packages/core/__test__/services/subscription.service.spec.ts @@ -4,6 +4,7 @@ import { ClientReadyState, ConsoleLoggerService, Event, + EventKind, EventUtils, Filter, MessageType, @@ -21,6 +22,7 @@ describe('SubscriptionService', () => { subscriptionService = new SubscriptionService( clientsMap, new ConsoleLoggerService(), + true, ); client = { readyState: ClientReadyState.OPEN, @@ -128,6 +130,43 @@ describe('SubscriptionService', () => { expect(client.send).not.toHaveBeenCalled(); }); + it('should not broadcast event to client if client is unauthorized', async () => { + const subscriptionId = 'subscriptionId'; + const filters = [{}] as Filter[]; + const event = { + id: 'id', + kind: EventKind.ENCRYPTED_DIRECT_MESSAGE, + } as Event; + + jest.spyOn(EventUtils, 'isMatchingFilter').mockReturnValue(true); + jest.spyOn(EventUtils, 'checkPermission').mockReturnValue(false); + + subscriptionService.subscribe(ctx, subscriptionId, filters); + await subscriptionService.broadcast(event); + + expect(client.send).not.toHaveBeenCalled(); + }); + + it('should broadcast event to client if nip-42 is disabled and client is unauthorized', async () => { + (subscriptionService as any).isNip42Enabled = false; + const subscriptionId = 'subscriptionId'; + const filters = [{}] as Filter[]; + const event = { + id: 'id', + kind: EventKind.ENCRYPTED_DIRECT_MESSAGE, + } as Event; + + jest.spyOn(EventUtils, 'isMatchingFilter').mockReturnValue(true); + jest.spyOn(EventUtils, 'checkPermission').mockReturnValue(false); + + subscriptionService.subscribe(ctx, subscriptionId, filters); + await subscriptionService.broadcast(event); + + expect(client.send).toHaveBeenCalledWith( + JSON.stringify([MessageType.EVENT, subscriptionId, event]), + ); + }); + it('should catch error', async () => { const subscriptionId = 'subscriptionId'; const filters = [{}] as Filter[]; diff --git a/packages/core/src/nostr-relay.ts b/packages/core/src/nostr-relay.ts index 159b0cf4..d27ffd7d 100644 --- a/packages/core/src/nostr-relay.ts +++ b/packages/core/src/nostr-relay.ts @@ -66,6 +66,7 @@ export class NostrRelay { this.subscriptionService = new SubscriptionService( this.clientContexts, logger, + !!options.domain, ); this.eventService = new EventService( eventRepository, diff --git a/packages/core/src/services/subscription.service.ts b/packages/core/src/services/subscription.service.ts index 6a1b4049..3014237a 100644 --- a/packages/core/src/services/subscription.service.ts +++ b/packages/core/src/services/subscription.service.ts @@ -12,6 +12,7 @@ export class SubscriptionService { constructor( private readonly clientsMap: Map, private readonly logger: Logger, + private readonly isNip42Enabled: boolean, ) {} subscribe( @@ -37,11 +38,14 @@ export class SubscriptionService { ctx.subscriptions.forEach((filters, subscriptionId) => { if ( - !filters.some(filter => EventUtils.isMatchingFilter(event, filter)) + filters.some(filter => + EventUtils.isMatchingFilter(event, filter), + ) && + (!this.isNip42Enabled || + EventUtils.checkPermission(event, ctx.pubkey)) ) { - return; + ctx.sendMessage(createOutgoingEventMessage(subscriptionId, event)); } - ctx.sendMessage(createOutgoingEventMessage(subscriptionId, event)); }); } } catch (error) {