diff --git a/src/@types/messages.ts b/src/@types/messages.ts index 534b78e..7830c80 100644 --- a/src/@types/messages.ts +++ b/src/@types/messages.ts @@ -16,6 +16,7 @@ export enum MessageType { export type IncomingMessage = ( | SubscribeMessage | IncomingEventMessage + | IncomingAuthMessage | UnsubscribeMessage ) & { [ContextMetadataKey]?: ContextMetadata @@ -53,6 +54,11 @@ export interface OutgoingEventMessage { } export interface OutgoingAuthMessage { + 0: MessageType.AUTH + 1: string +} + +export interface IncomingAuthMessage { 0: MessageType.AUTH 1: Event } diff --git a/src/adapters/web-socket-adapter.ts b/src/adapters/web-socket-adapter.ts index 2cdcc6a..ee50e13 100644 --- a/src/adapters/web-socket-adapter.ts +++ b/src/adapters/web-socket-adapter.ts @@ -6,7 +6,7 @@ import { randomBytes } from 'crypto' import { WebSocket } from 'ws' import { ContextMetadata, Factory } from '../@types/base' -import { createAuthEventMessage, createCommandResult, createNoticeMessage, createOutgoingEventMessage } from '../utils/messages' +import { createAuthMessage, createCommandResult, createNoticeMessage, createOutgoingEventMessage } from '../utils/messages' import { IAbortable, IMessageHandler } from '../@types/message-handlers' import { IncomingMessage, MessageType, OutgoingMessage } from '../@types/messages' import { IWebSocketAdapter, IWebSocketServerAdapter } from '../@types/adapters' @@ -188,10 +188,7 @@ export class WebSocketAdapter extends EventEmitter implements IWebSocketAdapter // Need to emit event? const challenge = this.setNewAuthChallenge() - this.webSocketServer.emit( - WebSocketServerAdapterEvent.Broadcast, - createAuthEventMessage(challenge) - ) + this.sendMessage(createAuthMessage(challenge)) return } @@ -201,15 +198,9 @@ export class WebSocketAdapter extends EventEmitter implements IWebSocketAdapter const challenge = this.setNewAuthChallenge() - this.webSocketServer.emit( - WebSocketServerAdapterEvent.Broadcast, - createCommandResult(message[1].id, false, 'rejected: unauthorized') - ) + this.sendMessage(createCommandResult(message[1].id, false, 'rejected: unauthorized')) - this.webSocketServer.emit( - WebSocketServerAdapterEvent.Broadcast, - createAuthEventMessage(challenge) - ) + this.sendMessage(createAuthMessage(challenge)) return } diff --git a/src/utils/messages.ts b/src/utils/messages.ts index a67a235..8639f70 100644 --- a/src/utils/messages.ts +++ b/src/utils/messages.ts @@ -1,9 +1,11 @@ import { + CommandResult, EndOfStoredEventsNotice, IncomingEventMessage, IncomingRelayedEventMessage, MessageType, NoticeMessage, + OutgoingAuthMessage, OutgoingMessage, SubscribeMessage, } from '../@types/messages' @@ -30,12 +32,12 @@ export const createEndOfStoredEventsNoticeMessage = ( } // NIP-20 -export const createCommandResult = (eventId: EventId, successful: boolean, message: string) => { +export const createCommandResult = (eventId: EventId, successful: boolean, message: string): CommandResult => { return [MessageType.OK, eventId, successful, message] } // NIP-42 -export const createAuthEventMessage = (challenge) => { +export const createAuthMessage = (challenge: string): OutgoingAuthMessage => { return [MessageType.AUTH, challenge] } diff --git a/test/integration/features/nip-01/nip-01.feature b/test/integration/features/nip-01/nip-01.feature index e8d7264..be0c2ca 100644 --- a/test/integration/features/nip-01/nip-01.feature +++ b/test/integration/features/nip-01/nip-01.feature @@ -72,7 +72,6 @@ Feature: NIP-01 And Alice subscribes to text_note events from Bob and set_metadata events from Charlie Then Alice receives 2 events from Bob and Charlie - @test Scenario: Alice is interested in Bob's events from back in November Given someone called Alice And someone called Bob diff --git a/test/integration/features/nip-01/nip-01.feature.ts b/test/integration/features/nip-01/nip-01.feature.ts index 0b3f14c..a3f3cc9 100644 --- a/test/integration/features/nip-01/nip-01.feature.ts +++ b/test/integration/features/nip-01/nip-01.feature.ts @@ -101,13 +101,13 @@ When(/(\w+) sends a set_metadata event/, async function(name: string) { this.parameters.events[name].push(event) }) -When(/^(\w+) sends a text_note event with content "([^"]+)"$/, async function(name: string, content: string) { +When(/^(\w+) sends a text_note event with content "([^"]+)"(?:\s+(successfully|unsuccessfully))?$/, async function(name: string, content: string, outcome: string) { const ws = this.parameters.clients[name] as WebSocket const { pubkey, privkey } = this.parameters.identities[name] const event: Event = await createEvent({ pubkey, kind: 1, content }, privkey) - await sendEvent(ws, event) + await sendEvent(ws, event, outcome !== 'unsuccessfully') this.parameters.events[name].push(event) }) diff --git a/test/integration/features/nip-42/nip-42.feature b/test/integration/features/nip-42/nip-42.feature index 0955cc1..e1782aa 100644 --- a/test/integration/features/nip-42/nip-42.feature +++ b/test/integration/features/nip-42/nip-42.feature @@ -2,5 +2,5 @@ Feature: NIP-42 Scenario: Alice gets an event by ID Given someone called Alice And the relay requires the client to authenticate - When Alice sends a text_note event with content "hello nostr" + When Alice sends a text_note event with content "hello nostr" unsuccessfully Then Alice receives an authentication challenge diff --git a/test/integration/features/nip-42/nip-42.feature.ts b/test/integration/features/nip-42/nip-42.feature.ts index 7bbab8f..4a4d708 100644 --- a/test/integration/features/nip-42/nip-42.feature.ts +++ b/test/integration/features/nip-42/nip-42.feature.ts @@ -5,7 +5,6 @@ import { } from '@cucumber/cucumber' import chai from 'chai' -import { EventKinds } from '../../../../src/constants/base' import { SettingsStatic } from '../../../../src/utils/settings' import sinonChai from 'sinon-chai' import { waitForAuth } from '../helpers' @@ -19,10 +18,11 @@ Given(/the relay requires the client to authenticate/, async function (this: Wor settings.authentication.enabled = true }) -Then(/(\w+) receives an authentication challenge "([^"]+?)"/, async function (name: string) { +Then(/(\w+) receives an authentication challenge/, async function (name: string) { const ws = this.parameters.clients[name] as WebSocket const outgoingAuthMessage = await waitForAuth(ws) - const event = outgoingAuthMessage[1] - expect(event.kind).to.equal(EventKinds.AUTH) + const challenge = outgoingAuthMessage[1] + expect(challenge).to.be.a.string + this.parameters.challenges[name].push(challenge) }) diff --git a/test/integration/features/shared.ts b/test/integration/features/shared.ts index 8c7b6db..bc85182 100644 --- a/test/integration/features/shared.ts +++ b/test/integration/features/shared.ts @@ -38,7 +38,9 @@ BeforeAll({ timeout: 1000 }, async function () { cacheClient = getCacheClient() dbClient = getMasterDbClient() rrDbClient = getReadReplicaDbClient() - await dbClient.raw('SELECT 1=1') + await dbClient.raw('DELETE FROM events') + await dbClient.raw('DELETE FROM invoices') + await dbClient.raw('DELETE FROM users') Sinon.stub(SettingsStatic, 'watchSettings') const settings = SettingsStatic.createSettings() @@ -66,6 +68,9 @@ Before(function () { this.parameters.subscriptions = {} this.parameters.clients = {} this.parameters.events = {} + this.parameters.challenges = {} + const settings = SettingsStatic.createSettings() + settings.authentication.enabled = false }) After(async function () { @@ -87,6 +92,7 @@ After(async function () { .map(({ pubkey }) => Buffer.from(pubkey, 'hex')), }).del() this.parameters.identities = {} + this.parameters.challenges = {} }) Given(/someone called (\w+)/, async function(name: string) { @@ -95,6 +101,8 @@ Given(/someone called (\w+)/, async function(name: string) { this.parameters.clients[name] = connection this.parameters.subscriptions[name] = [] this.parameters.events[name] = [] + this.parameters.challenges[name] = [] + const subject = new Subject() connection.once('close', subject.next.bind(subject))