schedule deletion of notes

This commit is contained in:
Maxime Cannoodt 2022-06-29 14:17:38 +02:00
parent d0de4040ef
commit dcf607c0dc
7 changed files with 70 additions and 38 deletions

View File

@ -6,5 +6,6 @@
ENVIRONMENT=dev
PORT=8080
CLEANUP_INTERVAL_SECONDS=60
FRONTEND_URL="http://localhost:3000"
DATABASE_URL="file:./dev.db"

View File

@ -9,7 +9,7 @@
"version": "0.0.1",
"license": "MIT",
"dependencies": {
"@prisma/client": "^3.15.2",
"@prisma/client": "^4.0.0",
"cors": "^2.8.5",
"dotenv": "^16.0.1",
"express": "^4.18.1",
@ -21,7 +21,7 @@
"@types/node": "^18.0.0",
"@types/sqlite3": "^3.1.8",
"nodemon": "^2.0.16",
"prisma": "^3.15.2",
"prisma": "^4.0.0",
"supertest": "^6.2.3",
"ts-node": "^10.8.1",
"typescript": "^4.7.4",
@ -128,15 +128,15 @@
}
},
"node_modules/@prisma/client": {
"version": "3.15.2",
"resolved": "https://registry.npmjs.org/@prisma/client/-/client-3.15.2.tgz",
"integrity": "sha512-ErqtwhX12ubPhU4d++30uFY/rPcyvjk+mdifaZO5SeM21zS3t4jQrscy8+6IyB0GIYshl5ldTq6JSBo1d63i8w==",
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/@prisma/client/-/client-4.0.0.tgz",
"integrity": "sha512-g1h2OGoRo7anBVQ9Cw3gsbjwPtvf7i0pkGxKeZICtwkvE5CZXW+xZF4FZdmrViYkKaAShbISL0teNpu9ecpf4g==",
"hasInstallScript": true,
"dependencies": {
"@prisma/engines-version": "3.15.1-1.461d6a05159055555eb7dfb337c9fb271cbd4d7e"
"@prisma/engines-version": "3.16.0-49.da41d2bb3406da22087b849f0e911199ba4fbf11"
},
"engines": {
"node": ">=12.6"
"node": ">=14.17"
},
"peerDependencies": {
"prisma": "*"
@ -148,16 +148,16 @@
}
},
"node_modules/@prisma/engines": {
"version": "3.15.1-1.461d6a05159055555eb7dfb337c9fb271cbd4d7e",
"resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-3.15.1-1.461d6a05159055555eb7dfb337c9fb271cbd4d7e.tgz",
"integrity": "sha512-NHlojO1DFTsSi3FtEleL9QWXeSF/UjhCW0fgpi7bumnNZ4wj/eQ+BJJ5n2pgoOliTOGv9nX2qXvmHap7rJMNmg==",
"version": "3.16.0-49.da41d2bb3406da22087b849f0e911199ba4fbf11",
"resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-3.16.0-49.da41d2bb3406da22087b849f0e911199ba4fbf11.tgz",
"integrity": "sha512-u/rG4lDHALolWBLr3yebZ+N2qImp3SDMcu7bHNJuRDaYvYEXy/MqfNRNEgd9GoPsXL3gofYf0VzJf2AmCG3YVw==",
"devOptional": true,
"hasInstallScript": true
},
"node_modules/@prisma/engines-version": {
"version": "3.15.1-1.461d6a05159055555eb7dfb337c9fb271cbd4d7e",
"resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-3.15.1-1.461d6a05159055555eb7dfb337c9fb271cbd4d7e.tgz",
"integrity": "sha512-e3k2Vd606efd1ZYy2NQKkT4C/pn31nehyLhVug6To/q8JT8FpiMrDy7zmm3KLF0L98NOQQcutaVtAPhzKhzn9w=="
"version": "3.16.0-49.da41d2bb3406da22087b849f0e911199ba4fbf11",
"resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-3.16.0-49.da41d2bb3406da22087b849f0e911199ba4fbf11.tgz",
"integrity": "sha512-PiZhdD624SrYEjyLboI0X7OugNbxUzDJx9v/6ldTKuqNDVUCmRH/Z00XwDi/dgM4FlqOSO+YiUsSiSKjxxG8cw=="
},
"node_modules/@sindresorhus/is": {
"version": "0.14.0",
@ -2949,20 +2949,20 @@
}
},
"node_modules/prisma": {
"version": "3.15.2",
"resolved": "https://registry.npmjs.org/prisma/-/prisma-3.15.2.tgz",
"integrity": "sha512-nMNSMZvtwrvoEQ/mui8L/aiCLZRCj5t6L3yujKpcDhIPk7garp8tL4nMx2+oYsN0FWBacevJhazfXAbV1kfBzA==",
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/prisma/-/prisma-4.0.0.tgz",
"integrity": "sha512-Dtsar03XpCBkcEb2ooGWO/WcgblDTLzGhPcustbehwlFXuTMliMDRzXsfygsgYwQoZnAUKRd1rhpvBNEUziOVw==",
"devOptional": true,
"hasInstallScript": true,
"dependencies": {
"@prisma/engines": "3.15.1-1.461d6a05159055555eb7dfb337c9fb271cbd4d7e"
"@prisma/engines": "3.16.0-49.da41d2bb3406da22087b849f0e911199ba4fbf11"
},
"bin": {
"prisma": "build/index.js",
"prisma2": "build/index.js"
},
"engines": {
"node": ">=12.6"
"node": ">=14.17"
}
},
"node_modules/promise-inflight": {
@ -4157,23 +4157,23 @@
}
},
"@prisma/client": {
"version": "3.15.2",
"resolved": "https://registry.npmjs.org/@prisma/client/-/client-3.15.2.tgz",
"integrity": "sha512-ErqtwhX12ubPhU4d++30uFY/rPcyvjk+mdifaZO5SeM21zS3t4jQrscy8+6IyB0GIYshl5ldTq6JSBo1d63i8w==",
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/@prisma/client/-/client-4.0.0.tgz",
"integrity": "sha512-g1h2OGoRo7anBVQ9Cw3gsbjwPtvf7i0pkGxKeZICtwkvE5CZXW+xZF4FZdmrViYkKaAShbISL0teNpu9ecpf4g==",
"requires": {
"@prisma/engines-version": "3.15.1-1.461d6a05159055555eb7dfb337c9fb271cbd4d7e"
"@prisma/engines-version": "3.16.0-49.da41d2bb3406da22087b849f0e911199ba4fbf11"
}
},
"@prisma/engines": {
"version": "3.15.1-1.461d6a05159055555eb7dfb337c9fb271cbd4d7e",
"resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-3.15.1-1.461d6a05159055555eb7dfb337c9fb271cbd4d7e.tgz",
"integrity": "sha512-NHlojO1DFTsSi3FtEleL9QWXeSF/UjhCW0fgpi7bumnNZ4wj/eQ+BJJ5n2pgoOliTOGv9nX2qXvmHap7rJMNmg==",
"version": "3.16.0-49.da41d2bb3406da22087b849f0e911199ba4fbf11",
"resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-3.16.0-49.da41d2bb3406da22087b849f0e911199ba4fbf11.tgz",
"integrity": "sha512-u/rG4lDHALolWBLr3yebZ+N2qImp3SDMcu7bHNJuRDaYvYEXy/MqfNRNEgd9GoPsXL3gofYf0VzJf2AmCG3YVw==",
"devOptional": true
},
"@prisma/engines-version": {
"version": "3.15.1-1.461d6a05159055555eb7dfb337c9fb271cbd4d7e",
"resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-3.15.1-1.461d6a05159055555eb7dfb337c9fb271cbd4d7e.tgz",
"integrity": "sha512-e3k2Vd606efd1ZYy2NQKkT4C/pn31nehyLhVug6To/q8JT8FpiMrDy7zmm3KLF0L98NOQQcutaVtAPhzKhzn9w=="
"version": "3.16.0-49.da41d2bb3406da22087b849f0e911199ba4fbf11",
"resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-3.16.0-49.da41d2bb3406da22087b849f0e911199ba4fbf11.tgz",
"integrity": "sha512-PiZhdD624SrYEjyLboI0X7OugNbxUzDJx9v/6ldTKuqNDVUCmRH/Z00XwDi/dgM4FlqOSO+YiUsSiSKjxxG8cw=="
},
"@sindresorhus/is": {
"version": "0.14.0",
@ -6209,12 +6209,12 @@
"dev": true
},
"prisma": {
"version": "3.15.2",
"resolved": "https://registry.npmjs.org/prisma/-/prisma-3.15.2.tgz",
"integrity": "sha512-nMNSMZvtwrvoEQ/mui8L/aiCLZRCj5t6L3yujKpcDhIPk7garp8tL4nMx2+oYsN0FWBacevJhazfXAbV1kfBzA==",
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/prisma/-/prisma-4.0.0.tgz",
"integrity": "sha512-Dtsar03XpCBkcEb2ooGWO/WcgblDTLzGhPcustbehwlFXuTMliMDRzXsfygsgYwQoZnAUKRd1rhpvBNEUziOVw==",
"devOptional": true,
"requires": {
"@prisma/engines": "3.15.1-1.461d6a05159055555eb7dfb337c9fb271cbd4d7e"
"@prisma/engines": "3.16.0-49.da41d2bb3406da22087b849f0e911199ba4fbf11"
}
},
"promise-inflight": {

View File

@ -11,7 +11,7 @@
"author": "Maxime Cannoodt (mcndt)",
"license": "MIT",
"dependencies": {
"@prisma/client": "^3.15.2",
"@prisma/client": "^4.0.0",
"cors": "^2.8.5",
"dotenv": "^16.0.1",
"express": "^4.18.1",
@ -23,7 +23,7 @@
"@types/node": "^18.0.0",
"@types/sqlite3": "^3.1.8",
"nodemon": "^2.0.16",
"prisma": "^3.15.2",
"prisma": "^4.0.0",
"supertest": "^6.2.3",
"ts-node": "^10.8.1",
"typescript": "^4.7.4",

Binary file not shown.

View File

@ -13,6 +13,7 @@ datasource db {
model EncryptedNote {
id String @id @default(cuid())
insert_time DateTime @default(now())
expire_time DateTime @default(now())
ciphertext String
hmac String
}

View File

@ -2,11 +2,15 @@ import "dotenv/config";
import express, { Express, Request, Response } from "express";
import cors from "cors";
import { PrismaClient, EncryptedNote } from "@prisma/client";
import { addDays } from "./util";
// Initialize middleware clients
const prisma = new PrismaClient();
const app: Express = express();
app.use(express.json());
// Allow CORS in dev mode.
if (process.env.ENVIRONMENT == "dev") {
app.use(
cors({
@ -15,8 +19,6 @@ if (process.env.ENVIRONMENT == "dev") {
);
}
app.use(express.json());
// start the Express server
app.listen(process.env.PORT, () => {
console.log(`server started at http://localhost:${process.env.PORT}`);
@ -25,7 +27,9 @@ app.listen(process.env.PORT, () => {
// Post new encrypted note
app.post("/note/", async (req: Request<{}, {}, EncryptedNote>, res) => {
const note = req.body;
const savedNote = await prisma.encryptedNote.create({ data: note });
const savedNote = await prisma.encryptedNote.create({
data: { ...note, expire_time: addDays(new Date(), 14) },
});
res.json({ view_url: `${process.env.FRONTEND_URL}/note/${savedNote.id}` });
});
@ -44,3 +48,24 @@ app.get("/note/:id", async (req, res) => {
app.use((req, res, next) => {
res.status(404).send();
});
// Clean up expired notes periodically
const interval =
Math.max(parseInt(<string>process.env.CLEANUP_INTERVAL_SECONDS) || 1, 1) *
1000;
setInterval(async () => {
try {
console.log("[Cleanup] Cleaning up expired notes...");
const deleted = await prisma.encryptedNote.deleteMany({
where: {
expire_time: {
lte: new Date(),
},
},
});
console.log(`[Cleanup] Deleted ${deleted.count} expired notes.`);
} catch (err) {
console.error(`[Cleanup] Error cleaning expired notes:`);
console.error(err);
}
}, interval);

5
server/util.ts Normal file
View File

@ -0,0 +1,5 @@
export function addDays(date: Date, days: number): Date {
var result = new Date(date);
result.setDate(result.getDate() + days);
return result;
}