diff --git a/src/middleware/auth98.ts b/src/middleware/auth98.ts index 90861826..280af908 100644 --- a/src/middleware/auth98.ts +++ b/src/middleware/auth98.ts @@ -2,7 +2,8 @@ import { type AppMiddleware } from '@/app.ts'; import { Conf } from '@/config.ts'; import { HTTPException } from '@/deps.ts'; import { type Event } from '@/event.ts'; -import { decode64Schema, jsonSchema, signedEventSchema } from '@/schema.ts'; +import { decode64Schema, jsonSchema } from '@/schema.ts'; +import { signedEventSchema } from '@/schemas/nostr.ts'; import { eventAge, findTag, sha256, Time } from '@/utils.ts'; const decodeEventSchema = decode64Schema.pipe(jsonSchema).pipe(signedEventSchema); diff --git a/src/schema.ts b/src/schema.ts index 635dff8b..646367e7 100644 --- a/src/schema.ts +++ b/src/schema.ts @@ -1,4 +1,4 @@ -import { verifySignature, z } from '@/deps.ts'; +import { z } from '@/deps.ts'; import type { Event } from './event.ts'; @@ -67,20 +67,6 @@ const relaySchema = z.custom((relay) => { } }); -const hexIdSchema = z.string().regex(/^[0-9a-f]{64}$/); - -const eventSchema = z.object({ - id: hexIdSchema, - kind: z.number(), - tags: z.array(z.array(z.string())), - content: z.string(), - created_at: z.number(), - pubkey: hexIdSchema, - sig: z.string(), -}); - -const signedEventSchema = eventSchema.refine(verifySignature); - const emojiTagSchema = z.tuple([z.literal('emoji'), z.string(), z.string().url()]); /** https://developer.mozilla.org/en-US/docs/Glossary/Base64#the_unicode_problem */ @@ -102,12 +88,10 @@ export { emojiTagSchema, filteredArray, hashtagSchema, - hexIdSchema, jsonSchema, type MetaContent, metaContentSchema, parseMetaContent, parseRelay, relaySchema, - signedEventSchema, }; diff --git a/src/schemas/nostr.ts b/src/schemas/nostr.ts index 9f42b4fe..1b318dbf 100644 --- a/src/schemas/nostr.ts +++ b/src/schemas/nostr.ts @@ -1,7 +1,23 @@ -import { z } from '@/deps.ts'; +import { verifySignature, z } from '@/deps.ts'; -import { hexIdSchema, signedEventSchema } from '../schema.ts'; +/** Schema to validate Nostr hex IDs such as event IDs and pubkeys. */ +const hexIdSchema = z.string().regex(/^[0-9a-f]{64}$/); +/** Nostr event schema. */ +const eventSchema = z.object({ + id: hexIdSchema, + kind: z.number(), + tags: z.array(z.array(z.string())), + content: z.string(), + created_at: z.number(), + pubkey: hexIdSchema, + sig: z.string(), +}); + +/** Nostr event schema that also verifies the event's signature. */ +const signedEventSchema = eventSchema.refine(verifySignature); + +/** Nostr relay filter schema. */ const filterSchema = z.object({ kinds: z.number().int().positive().array().optional(), ids: hexIdSchema.array().optional(), @@ -14,12 +30,11 @@ const filterSchema = z.object({ z.string().array(), )); +/** Client message to a Nostr relay. */ const clientMsgSchema = z.union([ z.tuple([z.literal('REQ'), z.string().min(1)]).rest(filterSchema), z.tuple([z.literal('EVENT'), signedEventSchema]), z.tuple([z.literal('CLOSE'), z.string().min(1)]), ]); -type Filter = z.infer; - -export { clientMsgSchema, filterSchema }; +export { clientMsgSchema, filterSchema, hexIdSchema, signedEventSchema }; diff --git a/src/sign.ts b/src/sign.ts index 228496f7..c0bebca2 100644 --- a/src/sign.ts +++ b/src/sign.ts @@ -1,6 +1,6 @@ import { type AppContext } from '@/app.ts'; import { getEventHash, getPublicKey, getSignature, HTTPException, z } from '@/deps.ts'; -import { signedEventSchema } from '@/schema.ts'; +import { signedEventSchema } from '@/schemas/nostr.ts'; import { ws } from '@/stream.ts'; import type { Event, EventTemplate, SignedEvent } from '@/event.ts'; diff --git a/src/trends.ts b/src/trends.ts index 3bb19d44..aa1ea2dc 100644 --- a/src/trends.ts +++ b/src/trends.ts @@ -1,5 +1,6 @@ import { Sqlite } from '@/deps.ts'; -import { hashtagSchema, hexIdSchema } from '@/schema.ts'; +import { hashtagSchema } from '@/schema.ts'; +import { hexIdSchema } from '@/schemas/nostr.ts'; import { Time } from '@/utils.ts'; import { generateDateRange } from '@/utils/time.ts';