validate POST body form
This commit is contained in:
parent
1d824d5f07
commit
276ac5cfe0
42
server/package-lock.json
generated
42
server/package-lock.json
generated
@ -11,6 +11,7 @@
|
||||
"dependencies": {
|
||||
"@prisma/client": "^4.0.0",
|
||||
"body-parser": "^1.20.0",
|
||||
"class-validator": "^0.13.2",
|
||||
"dotenv": "^16.0.1",
|
||||
"express": "^4.18.1",
|
||||
"express-rate-limit": "^6.4.0",
|
||||
@ -930,6 +931,15 @@
|
||||
"integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/class-validator": {
|
||||
"version": "0.13.2",
|
||||
"resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.13.2.tgz",
|
||||
"integrity": "sha512-yBUcQy07FPlGzUjoLuUfIOXzgynnQPPruyK1Ge2B74k9ROwnle1E+NxLWnUv5OLU8hA/qL5leAE9XnXq3byaBw==",
|
||||
"dependencies": {
|
||||
"libphonenumber-js": "^1.9.43",
|
||||
"validator": "^13.7.0"
|
||||
}
|
||||
},
|
||||
"node_modules/clean-stack": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
|
||||
@ -2935,6 +2945,11 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/libphonenumber-js": {
|
||||
"version": "1.10.7",
|
||||
"resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.10.7.tgz",
|
||||
"integrity": "sha512-jZXLCCWMe1b/HXkjiLeYt2JsytZMcqH26jLFIdzFDFF0xvSUWrYKyvPlyPG+XJzEyKUFbcZxLdWGMwQsWaHDxQ=="
|
||||
},
|
||||
"node_modules/load-json-file": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz",
|
||||
@ -5260,6 +5275,14 @@
|
||||
"spdx-expression-parse": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/validator": {
|
||||
"version": "13.7.0",
|
||||
"resolved": "https://registry.npmjs.org/validator/-/validator-13.7.0.tgz",
|
||||
"integrity": "sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw==",
|
||||
"engines": {
|
||||
"node": ">= 0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/vary": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
|
||||
@ -6265,6 +6288,15 @@
|
||||
"integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==",
|
||||
"dev": true
|
||||
},
|
||||
"class-validator": {
|
||||
"version": "0.13.2",
|
||||
"resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.13.2.tgz",
|
||||
"integrity": "sha512-yBUcQy07FPlGzUjoLuUfIOXzgynnQPPruyK1Ge2B74k9ROwnle1E+NxLWnUv5OLU8hA/qL5leAE9XnXq3byaBw==",
|
||||
"requires": {
|
||||
"libphonenumber-js": "^1.9.43",
|
||||
"validator": "^13.7.0"
|
||||
}
|
||||
},
|
||||
"clean-stack": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
|
||||
@ -7685,6 +7717,11 @@
|
||||
"package-json": "^6.3.0"
|
||||
}
|
||||
},
|
||||
"libphonenumber-js": {
|
||||
"version": "1.10.7",
|
||||
"resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.10.7.tgz",
|
||||
"integrity": "sha512-jZXLCCWMe1b/HXkjiLeYt2JsytZMcqH26jLFIdzFDFF0xvSUWrYKyvPlyPG+XJzEyKUFbcZxLdWGMwQsWaHDxQ=="
|
||||
},
|
||||
"load-json-file": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz",
|
||||
@ -9417,6 +9454,11 @@
|
||||
"spdx-expression-parse": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"validator": {
|
||||
"version": "13.7.0",
|
||||
"resolved": "https://registry.npmjs.org/validator/-/validator-13.7.0.tgz",
|
||||
"integrity": "sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw=="
|
||||
},
|
||||
"vary": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
|
||||
|
@ -18,6 +18,7 @@
|
||||
"dependencies": {
|
||||
"@prisma/client": "^4.0.0",
|
||||
"body-parser": "^1.20.0",
|
||||
"class-validator": "^0.13.2",
|
||||
"dotenv": "^16.0.1",
|
||||
"express": "^4.18.1",
|
||||
"express-rate-limit": "^6.4.0",
|
||||
|
@ -3,9 +3,10 @@ import request from "supertest";
|
||||
import { describe, it, expect } from "vitest";
|
||||
import prisma from "./client";
|
||||
|
||||
// const testNote with base64 ciphertext and hmac
|
||||
const testNote = {
|
||||
ciphertext: "sample_ciphertext",
|
||||
hmac: "sample_hmac",
|
||||
ciphertext: Buffer.from("sample_ciphertext").toString("base64"),
|
||||
hmac: Buffer.from("sample_hmac").toString("base64"),
|
||||
};
|
||||
|
||||
describe("GET /api/note", () => {
|
||||
@ -78,6 +79,11 @@ describe("POST /api/note", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("Returns a bad request on invalid POST body", async () => {
|
||||
const res = await request(app).post("/api/note").send({});
|
||||
expect(res.statusCode).toBe(400);
|
||||
});
|
||||
|
||||
it("returns a valid view_url on correct POST body", async () => {
|
||||
// Make post request
|
||||
let res = await request(app).post("/api/note").send(testNote);
|
||||
|
@ -1,5 +1,5 @@
|
||||
import "dotenv/config";
|
||||
import express, { Express, Request } from "express";
|
||||
import express, { Express, Request, Response } from "express";
|
||||
import { EncryptedNote } from "@prisma/client";
|
||||
import { addDays } from "./util";
|
||||
import helmet from "helmet";
|
||||
@ -8,6 +8,8 @@ import pinoHttp from "pino-http";
|
||||
import logger from "./logger";
|
||||
import prisma from "./client";
|
||||
import bodyParser from "body-parser";
|
||||
import { NotePostRequest } from "./model/NotePostRequest";
|
||||
import { validateOrReject } from "class-validator";
|
||||
|
||||
// Initialize middleware clients
|
||||
const app: Express = express();
|
||||
@ -48,7 +50,7 @@ const getLimiter = rateLimit({
|
||||
app.use(bodyParser.json({ limit: "400k" }));
|
||||
|
||||
// Get encrypted note
|
||||
app.get("/api/note/:id", getLimiter, (req, res, next) => {
|
||||
app.get("/api/note/:id", getLimiter, (req: Request, res: Response, next) => {
|
||||
prisma.encryptedNote
|
||||
.findUnique({
|
||||
where: { id: req.params.id },
|
||||
@ -63,24 +65,28 @@ app.get("/api/note/:id", getLimiter, (req, res, next) => {
|
||||
});
|
||||
|
||||
// Post new encrypted note
|
||||
app.post(
|
||||
"/api/note/",
|
||||
postLimiter,
|
||||
(req: Request<{}, {}, EncryptedNote>, res, next) => {
|
||||
const note = req.body;
|
||||
prisma.encryptedNote
|
||||
.create({
|
||||
data: { ...note, expire_time: addDays(new Date(), 30) },
|
||||
})
|
||||
.then((savedNote) => {
|
||||
res.json({
|
||||
view_url: `${process.env.FRONTEND_URL}/note/${savedNote.id}`,
|
||||
expire_time: savedNote.expire_time,
|
||||
});
|
||||
})
|
||||
.catch(next);
|
||||
}
|
||||
);
|
||||
app.post("/api/note/", postLimiter, (req: Request, res: Response, next) => {
|
||||
const notePostRequest = new NotePostRequest();
|
||||
Object.assign(notePostRequest, req.body);
|
||||
validateOrReject(notePostRequest).catch((err) => {
|
||||
res.status(400).send(err.message);
|
||||
});
|
||||
const note = notePostRequest as EncryptedNote;
|
||||
prisma.encryptedNote
|
||||
.create({
|
||||
data: {
|
||||
...note,
|
||||
expire_time: addDays(new Date(), 30),
|
||||
},
|
||||
})
|
||||
.then((savedNote) => {
|
||||
res.json({
|
||||
view_url: `${process.env.FRONTEND_URL}/note/${savedNote.id}`,
|
||||
expire_time: savedNote.expire_time,
|
||||
});
|
||||
})
|
||||
.catch(next);
|
||||
});
|
||||
|
||||
// For testing purposes
|
||||
app.get("/api/test", (req, res, next) => {
|
||||
|
12
server/src/model/NotePostRequest.ts
Normal file
12
server/src/model/NotePostRequest.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import { IsBase64 } from "class-validator";
|
||||
|
||||
/**
|
||||
* Request body for creating a note
|
||||
*/
|
||||
export class NotePostRequest {
|
||||
@IsBase64()
|
||||
ciphertext: string | undefined;
|
||||
|
||||
@IsBase64()
|
||||
hmac: string | undefined;
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"experimentalDecorators": true,
|
||||
"sourceMap": true,
|
||||
"outDir": "./build",
|
||||
"lib": ["esnext"],
|
||||
|
Loading…
Reference in New Issue
Block a user