From 72b7f4b9790bfb29b0f57b6a2617595f9e16159d Mon Sep 17 00:00:00 2001 From: Daniel Cadenas Date: Tue, 16 Jul 2024 18:28:16 -0300 Subject: [PATCH 1/5] Fix underscore name for a root domain --- src/middlewares/extractValidatedName.js | 13 ++++++++++- src/nameRecord.js | 18 +++++++++------ test/app.test.js | 30 +++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 8 deletions(-) diff --git a/src/middlewares/extractValidatedName.js b/src/middlewares/extractValidatedName.js index 7e2311c..b95aafe 100644 --- a/src/middlewares/extractValidatedName.js +++ b/src/middlewares/extractValidatedName.js @@ -20,7 +20,18 @@ function extractName(req) { let name = nameFromQueryOrBody; if (nameFromQueryOrBody === "_") { - name = validateAndReturnSubdomain(nonRootSubdomains); + if (!nonRootSubdomains) { + throw new AppError( + 422, + "The _ format requires a corresponding subdomain as the NIP-05 name." + ); + } + + if (nonRootSubdomains === config.rootDomain) { + name = "_"; + } else { + name = nonRootSubdomains; + } } return validateName(name); diff --git a/src/nameRecord.js b/src/nameRecord.js index d5e38fa..0596305 100644 --- a/src/nameRecord.js +++ b/src/nameRecord.js @@ -29,13 +29,6 @@ export function validateName(name) { throw new AppError(422, "Name is required."); } - if (name.length < 3) { - throw new AppError( - 422, - `Name '${name}' should have more than 3 characters.` - ); - } - if (name.startsWith("-")) { throw new AppError(422, `Name '${name}' should not start with a hyphen -.`); } @@ -44,6 +37,17 @@ export function validateName(name) { throw new AppError(422, `Name '${name}' should not start with a hyphen -.`); } + if (name === "_") { + return name; + } + + if (name.length < 3) { + throw new AppError( + 422, + `Name '${name}' should have more than 3 characters.` + ); + } + if (name.includes("_")) { throw new AppError( 422, diff --git a/test/app.test.js b/test/app.test.js index 6b82545..2b1eb3f 100644 --- a/test/app.test.js +++ b/test/app.test.js @@ -302,6 +302,36 @@ describe("Nostr NIP 05 API tests", () => { }); }); + it.only("should store and retrieve Nostr NIP 05 data through an empty subdomain", async () => { + const userData = createUserPayload({ name: "_" }); + + await request(app) + .post("/api/names") + .set("Host", "nos.social") + .set("Authorization", `Nostr ${nip98PostAuthToken}`) + .send(userData) + .expect(200); + + const getResponse = await request(app) + .get("/.well-known/nostr.json") + .set("Host", "nos.social") + .query({ name: "_" }) + .expect(200); + + const jsonResponse = JSON.parse(getResponse.text); + + expect(jsonResponse).toEqual({ + names: { _: config.servicePubkey }, + relays: { + [config.servicePubkey]: [ + "wss://relay1.com", + "wss://relay2.com", + "wss://relay.nos.social", + ], + }, + }); + }); + it("should not use components of the root domain as a subdomain", async () => { const userData = createUserPayload({ name: "nos" }); From 7830fbd21e4f6e9426c2e81b726948ac23bfb2cd Mon Sep 17 00:00:00 2001 From: Daniel Cadenas Date: Tue, 16 Jul 2024 18:36:16 -0300 Subject: [PATCH 2/5] Ignore config dir for coverage calculation --- jest.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jest.config.js b/jest.config.js index f2f402f..7f62af8 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,7 +1,7 @@ /** @type {import('jest').Config} */ export default { - modulePathIgnorePatterns: ["./config/"], + modulePathIgnorePatterns: ["config"], coverageThreshold: { global: { branches: 75, From 1684bbcb4a42caafdd26e1cd8700a83dc72236db Mon Sep 17 00:00:00 2001 From: Daniel Cadenas Date: Tue, 16 Jul 2024 18:41:05 -0300 Subject: [PATCH 3/5] One more try to fix coverage report --- jest.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jest.config.js b/jest.config.js index 7f62af8..61075d4 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,7 +1,7 @@ /** @type {import('jest').Config} */ export default { - modulePathIgnorePatterns: ["config"], + coveragePathIgnorePatterns: ["/config/"], coverageThreshold: { global: { branches: 75, From 7fc7f99387a6c7c71fd8187d1364ac15474731d0 Mon Sep 17 00:00:00 2001 From: Daniel Cadenas Date: Tue, 16 Jul 2024 18:43:19 -0300 Subject: [PATCH 4/5] Is this needed too --- jest.config.js | 1 + 1 file changed, 1 insertion(+) diff --git a/jest.config.js b/jest.config.js index 61075d4..6d6d7e8 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,6 +1,7 @@ /** @type {import('jest').Config} */ export default { + modulePathIgnorePatterns: ["/config/"], coveragePathIgnorePatterns: ["/config/"], coverageThreshold: { global: { From bb29b904b3a0acdddbc60bf26b28891962a39d01 Mon Sep 17 00:00:00 2001 From: Daniel Cadenas Date: Tue, 16 Jul 2024 18:53:41 -0300 Subject: [PATCH 5/5] Better test, remove unused func --- src/middlewares/extractValidatedName.js | 11 ----------- test/app.test.js | 8 +++++++- 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/src/middlewares/extractValidatedName.js b/src/middlewares/extractValidatedName.js index b95aafe..b31da02 100644 --- a/src/middlewares/extractValidatedName.js +++ b/src/middlewares/extractValidatedName.js @@ -15,7 +15,6 @@ function extractName(req) { validateDomain(host); const nonRootSubdomains = host.split(`.${config.rootDomain}`).find(Boolean); - const nameFromQueryOrBody = getNameFromReq(req); let name = nameFromQueryOrBody; @@ -67,13 +66,3 @@ function validateDomain(host) { ); } } - -function validateAndReturnSubdomain(nonRootSubdomains) { - if (!nonRootSubdomains) { - throw new AppError( - 422, - "The _ format requires a corresponding subdomain as the NIP-05 name." - ); - } - return nonRootSubdomains; -} diff --git a/test/app.test.js b/test/app.test.js index 2b1eb3f..a0d11aa 100644 --- a/test/app.test.js +++ b/test/app.test.js @@ -261,6 +261,12 @@ describe("Nostr NIP 05 API tests", () => { .send(userData) .expect(200); + await request(app) + .get("/.well-known/webfinger") + .set("Host", "nos.social") + .query({ resource: "acctWRONG:bob@nos.social" }) + .expect(422); + const getResponse = await request(app) .get("/.well-known/webfinger") .set("Host", "nos.social") @@ -302,7 +308,7 @@ describe("Nostr NIP 05 API tests", () => { }); }); - it.only("should store and retrieve Nostr NIP 05 data through an empty subdomain", async () => { + it("should store and retrieve Nostr NIP 05 data through an empty subdomain", async () => { const userData = createUserPayload({ name: "_" }); await request(app)