From 8a126507d85cb063ac6e34f65b5d2edff2a66f7e Mon Sep 17 00:00:00 2001 From: Daniel Cadenas Date: Tue, 20 Feb 2024 11:46:09 -0300 Subject: [PATCH] More validations, shorter logs --- config/test.js | 13 +++++---- package.json | 1 - src/logger.js | 23 ++++----------- src/middlewares/extractNip05Name.js | 24 ++++++++++++++-- src/schemas.js | 2 +- test/app.test.js | 44 +++++++++++++++++++++++++++++ 6 files changed, 79 insertions(+), 28 deletions(-) diff --git a/config/test.js b/config/test.js index 3894db6..744fd7e 100644 --- a/config/test.js +++ b/config/test.js @@ -1,7 +1,8 @@ export default { - redis: { - db: 2, - }, - logLevel: "fatal", - servicePubkey: '6c815df9b3e7f43492c232aba075b5fa5b6a60b731ce6ccfc7c1e8bd2adcceb2', -}; \ No newline at end of file + redis: { + db: 2, + }, + logLevel: "fatal", + servicePubkey: + "6c815df9b3e7f43492c232aba075b5fa5b6a60b731ce6ccfc7c1e8bd2adcceb2", +}; diff --git a/package.json b/package.json index 9977ee8..1eaffe1 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,6 @@ "nostr-tools": "^1.17.0", "pino": "^8.17.1", "pino-http": "^8.6.0", - "pino-pretty": "^10.3.0", "prom-client": "^15.1.0" }, "devDependencies": { diff --git a/src/logger.js b/src/logger.js index 7b33590..06cfa31 100644 --- a/src/logger.js +++ b/src/logger.js @@ -1,21 +1,8 @@ -import pino, { transport as _transport, stdTimeFunctions } from 'pino'; -import config from '../config/index.js'; - -const transport = _transport({ - targets: [ - { - target: 'pino-pretty', - options: { - colorize: true, - minimumLevel: config.logLevel, - } - }, - ], -}); +import pino from "pino"; +import config from "../config/index.js"; export default pino({ level: config.logLevel, - timestamp: stdTimeFunctions.isoTime, -}, - transport -); + timestamp: pino.stdTimeFunctions.isoTime, + prettyPrint: false, // Ensuring logs are in JSON format, single-line +}); diff --git a/src/middlewares/extractNip05Name.js b/src/middlewares/extractNip05Name.js index b1296a6..30bef1e 100644 --- a/src/middlewares/extractNip05Name.js +++ b/src/middlewares/extractNip05Name.js @@ -17,11 +17,31 @@ function extractName(req) { const nameFromQueryOrBody = req.query.name || req.params.name || req.body.name; + let name = nameFromQueryOrBody; if (nameFromQueryOrBody === "_") { - return validateAndReturnSubdomain(nonRootSubdomains); + name = validateAndReturnSubdomain(nonRootSubdomains); } - return nameFromQueryOrBody; + validateName(name); + + return name; +} + +function validateName(name) { + 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.`); + } + + if (name.endsWith("-")) { + throw new AppError(422, `Name '${name}' should not start with a hyphen.`); + } } function validateDomain(host) { diff --git a/src/schemas.js b/src/schemas.js index d3d969d..8a7ed90 100644 --- a/src/schemas.js +++ b/src/schemas.js @@ -1,6 +1,6 @@ const pubkeyPattern = "^[a-fA-F0-9]{64}$"; // We accept uppercase but we will convert everything to lowercase -const namePattern = "^[a-zA-Z0-9-_.]+$"; +const namePattern = "^[a-zA-Z0-9-_]+$"; const maxLength = 30; export const postNip05 = { diff --git a/test/app.test.js b/test/app.test.js index 91d1b1d..02ae124 100644 --- a/test/app.test.js +++ b/test/app.test.js @@ -100,6 +100,50 @@ describe("Nostr NIP 05 API tests", () => { .expect(422); }); + it("should fail if the name is too short", async () => { + const userData = createUserData({ name: "a" }); + + await request(app) + .post("/api/names") + .set("Host", "nos.social") + .set("Authorization", `Nostr ${nip98PostAuthToken}`) + .send(userData) + .expect(422); + }); + + it("should fail if the name starts with -", async () => { + const userData = createUserData({ name: "-aa" }); + + await request(app) + .post("/api/names") + .set("Host", "nos.social") + .set("Authorization", `Nostr ${nip98PostAuthToken}`) + .send(userData) + .expect(422); + }); + + it("should fail if the name ends with -", async () => { + const userData = createUserData({ name: "aa-" }); + + await request(app) + .post("/api/names") + .set("Host", "nos.social") + .set("Authorization", `Nostr ${nip98PostAuthToken}`) + .send(userData) + .expect(422); + }); + + it("should fail if the name includes a dot", async () => { + const userData = createUserData({ name: "aa." }); + + await request(app) + .post("/api/names") + .set("Host", "nos.social") + .set("Authorization", `Nostr ${nip98PostAuthToken}`) + .send(userData) + .expect(422); + }); + it("should fail if the name is not found", async () => { await request(app) .get("/.well-known/nostr.json")