From 85ed4dc8d6d188be9e2cbc4c83dfa75a47740329 Mon Sep 17 00:00:00 2001 From: BlowaterNostr Date: Mon, 29 Apr 2024 21:41:55 +0800 Subject: [PATCH] refactor --- deploy/example.ts | 15 +------- graphql-schema.ts | 2 +- main.tsx | 91 ++++++++++++++++++++++++++++------------------ resolvers/nip11.ts | 50 ++++++++----------------- 4 files changed, 74 insertions(+), 84 deletions(-) diff --git a/deploy/example.ts b/deploy/example.ts index 4b3f4d0..744cf65 100644 --- a/deploy/example.ts +++ b/deploy/example.ts @@ -1,18 +1,5 @@ -import { PublicKey } from "../_libs.ts"; import { run } from "../main.tsx"; -const relayed_pubkey = Deno.env.get("relayed_pubkey"); -if (!relayed_pubkey) { - console.error("Please set the environment variable 'relayed_pubkey'"); - Deno.exit(1); -} - -const pubkey = PublicKey.FromString(relayed_pubkey); -if (pubkey instanceof Error) { - console.error(pubkey); - Deno.exit(1); -} - const relay = await run({ port: 8080, default_policy: { @@ -21,7 +8,7 @@ const relay = await run({ default_information: { name: "Relayed Example", description: "A lightweight relay written in Deno.", - pubkey, + pubkey: "public key", contact: "", icon: "", }, diff --git a/graphql-schema.ts b/graphql-schema.ts index eefe92f..c3bcf03 100644 --- a/graphql-schema.ts +++ b/graphql-schema.ts @@ -14,7 +14,7 @@ export const typeDefs = gql` add_allow(kind: Int, pubkey: String, ): Policy! remove_allow(kind: Int, pubkey: String, ): Policy! set_policy(kind: Int, read: Boolean, write: Boolean): Policy! - set_relay_information(name: String, description: String, pubkey: String, contact: String, icon: String): RelayInformation! + set_relay_information(name: String, description: String, contact: String, icon: String): RelayInformation! } type Events { diff --git a/main.tsx b/main.tsx index 981e283..e6bcf14 100644 --- a/main.tsx +++ b/main.tsx @@ -48,25 +48,49 @@ export type Relay = { block?: Set; }) => Promise; get_policy: (kind: NostrKind) => Promise; - set_relay_information: (args: RelayInformationStringify) => Promise; + set_relay_information: (args: { + name?: string; + description?: string; + contact?: string; + icon?: string; + }) => Promise; get_relay_information: () => Promise; default_policy: DefaultPolicy; }; +const ENV_relayed_pubkey = "relayed_pubkey"; + export async function run(args: { port: number; admin?: PublicKey; - default_information: RelayInformation; default_policy: DefaultPolicy; + default_information?: RelayInformationStringify; kv?: Deno.Kv; }): Promise { - const connections = new Map(); + // argument checking if (args.kv == undefined) { args.kv = await Deno.openKv(); } - const { port, default_policy, default_information } = args; + let admin_pubkey: string | undefined | PublicKey | Error = args.default_information?.pubkey; + if (admin_pubkey == undefined) { + const env_pubkey = Deno.env.get(ENV_relayed_pubkey); + if (env_pubkey == undefined) { + return new Error( + "public key is not set. Please set env var $relayed_pubkey or pass default_information.pubkey in the argument", + ); + } + admin_pubkey = env_pubkey; + } + + admin_pubkey = PublicKey.FromString(admin_pubkey); + if (admin_pubkey instanceof Error) { + return admin_pubkey; + } + const { port, default_policy } = args; + /////////////// + const connections = new Map(); let resolve_hostname; const hostname = new Promise((resolve) => { resolve_hostname = resolve; @@ -76,7 +100,10 @@ export async function run(args: { const policyStore = new PolicyStore(default_policy, args.kv, await get_all_policies()); const relayInformationStore = new RelayInformationStore( args.kv, - default_information, + { + ...args.default_information, + pubkey: admin_pubkey, + }, ); const eventStore = await EventStore.New(args.kv); @@ -152,9 +179,9 @@ async (req: Request, info: Deno.ServeHandlerInfo) => { if (!body) { return new Response(`{"errors":"request body is null"}`, { status: 400 }); } - const result = await verifyToken(body, args.relayInformationStore); - if (!result.success) { - return new Response(JSON.stringify(result), { status: 400 }); + const error = await verifyToken(body, args.relayInformationStore); + if (error instanceof Error) { + return new Response(JSON.stringify(error.message), { status: 400 }); } else { const auth = btoa(JSON.stringify(body)); const headers = new Headers(); @@ -209,9 +236,11 @@ async (req: Request) => { console.log(`get token: ${token}`); const event = JSON.parse(atob(token)); console.log(`get event: ${JSON.stringify(event)}`); - const body = await verifyToken(event, args.relayInformationStore); - if (!body.success) { - return new Response(`{"errors":"${body.error}"}`); + const error = await verifyToken(event, args.relayInformationStore); + if (error instanceof Error) { + return new Response(JSON.stringify({ + errors: [error.message], + })); } const result = await gql.graphql({ schema: schema, @@ -221,7 +250,9 @@ async (req: Request) => { }); return new Response(JSON.stringify(result)); } catch (error) { - return new Response(`{"errors":"${error}"}`); + return new Response(JSON.stringify({ + errors: [`${error}`], + })); } } else if (req.method == "GET") { const res = new Response(graphiql); @@ -264,29 +295,19 @@ const information_handler = async (args: { relayInformationStore: RelayInformati }; async function verifyToken(event: NostrEvent, relayInformationStore: RelayInformationStore) { - try { - if (!await verifyEvent(event)) { - throw new Error("token not verified"); - } - const pubkey = PublicKey.FromString(event.pubkey); - if (pubkey instanceof Error) { - throw new Error("pubkey not valid"); - } - const storeInformation = await relayInformationStore.resolveRelayInformation(); - if (storeInformation instanceof Error) { - throw new Error("store pubkey not valid"); - } - if (pubkey.hex !== storeInformation.pubkey.hex) { - throw new Error("not admin"); - } - return { - success: true, - }; - } catch (error) { - return { - success: false, - error: error.toString(), - }; + if (!await verifyEvent(event)) { + return new Error("token not verified"); + } + const pubkey = PublicKey.FromString(event.pubkey); + if (pubkey instanceof Error) { + return pubkey; + } + const storeInformation = await relayInformationStore.resolveRelayInformation(); + if (storeInformation instanceof Error) { + return storeInformation; + } + if (pubkey.hex !== storeInformation.pubkey.hex) { + return new Error("your pubkey is not an admin"); } } diff --git a/resolvers/nip11.ts b/resolvers/nip11.ts index 6521d81..6cc86a1 100644 --- a/resolvers/nip11.ts +++ b/resolvers/nip11.ts @@ -16,9 +16,9 @@ export type RelayInformationParsed = { } & RelayInfomationBase; export type RelayInformation = { + pubkey: PublicKey; name?: string; description?: string; - pubkey: PublicKey; contact?: string; supported_nips?: number[]; software?: string; @@ -37,55 +37,37 @@ const not_modifiable_information: { }; export class RelayInformationStore { - default_information: RelayInformation; - constructor( private kv: Deno.Kv, - default_information: RelayInformation, - ) { - this.default_information = default_information; - } + public default_information: RelayInformation, + ) {} resolveRelayInformation = async (): Promise => { - const store_information_i = - (await this.kv.get(["relay_information"])).value; - if (!store_information_i) { + const entry = await this.kv.get(["relay_information"]); + if (!entry.value) { return { ...this.default_information, ...not_modifiable_information }; } - const store_information = informationPubkeyParse(store_information_i); - if (store_information instanceof Error) { - return store_information; - } - return { ...this.default_information, ...store_information, ...not_modifiable_information }; + + return { ...this.default_information, ...entry.value, ...not_modifiable_information }; }; - set_relay_information = async (args: RelayInformationStringify): Promise => { + set_relay_information = async (args: { + name?: string; + description?: string; + contact?: string; + icon?: string; + }): Promise => { const old_information = await this.resolveRelayInformation(); if (old_information instanceof Error) { return old_information; } - const input_information = informationPubkeyParse(args); - if (input_information instanceof Error) { - return input_information; - } - const new_information = { ...old_information, ...input_information }; - const store_new_information = informationPubkeyStringify(new_information); - await this.kv.set(["relay_information"], store_new_information); + + const new_information = { ...old_information, ...args }; + await this.kv.set(["relay_information"], new_information); return { ...new_information, ...not_modifiable_information }; }; } -export function informationPubkeyParse(info: RelayInformationStringify): RelayInformationParsed | Error { - if (!info.pubkey) { - return info as RelayInfomationBase; - } - const pubkey = PublicKey.FromString(info.pubkey); - if (pubkey instanceof Error) { - return pubkey; - } - return { ...info, pubkey }; -} - export function informationPubkeyStringify(info: RelayInformationParsed): RelayInformationStringify { if (!info.pubkey) { return info as RelayInfomationBase;