diff --git a/package-lock.json b/package-lock.json index 1b07f1d..3d70627 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,7 +13,8 @@ "@koa/ejs": "5.1.0", "@koa/router": "13.0.1", "koa": "2.15.3", - "koa-static": "5.0.0" + "koa-static": "5.0.0", + "nanoid": "5.0.9" }, "devDependencies": { "esbuild": "0.24.2" @@ -1352,6 +1353,24 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "license": "MIT" }, + "node_modules/nanoid": { + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.0.9.tgz", + "integrity": "sha512-Aooyr6MXU6HpvvWXKoVoXwKMs/KyVakWwg7xQfv5/S/RIgJMy0Ifa45H9qqYy7pTCszrHzP21Uk4PZq2HpEM8Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.js" + }, + "engines": { + "node": "^18 || >=20" + } + }, "node_modules/negotiator": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", diff --git a/package.json b/package.json index f5af5e6..bce4783 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,8 @@ "@koa/ejs": "5.1.0", "@koa/router": "13.0.1", "koa": "2.15.3", - "koa-static": "5.0.0" + "koa-static": "5.0.0", + "nanoid": "5.0.9" }, "devDependencies": { "esbuild": "0.24.2" diff --git a/server.js b/server.js index 940313a..43f7aa7 100644 --- a/server.js +++ b/server.js @@ -2,7 +2,7 @@ import Koa from "koa"; import serve from "koa-static"; import render from "@koa/ejs"; import { bodyParser } from "@koa/bodyparser"; -import { router } from "./src/router.js"; +import { router } from "./src/routes.js"; import { IS_PROD, BIND, PORT, LIMIT_SIZE } from "./src/constants.js"; const app = new Koa(); diff --git a/src/constants.js b/src/constants.js index 583b50b..8eaf5fb 100644 --- a/src/constants.js +++ b/src/constants.js @@ -1,5 +1,6 @@ export const PORT = process.env.PORT; export const BIND = process.env.BIND; +export const BASE_URL = process.env.BASE_URL; export const IS_PROD = process.env.NODE_ENV?.startsWith("prod"); diff --git a/src/create.js b/src/create.js new file mode 100644 index 0000000..5a2e669 --- /dev/null +++ b/src/create.js @@ -0,0 +1,28 @@ +import { nanoid } from "nanoid"; +import { BASE_URL } from "./constants.js"; +// keep these vars on frontend as its needed to decrypt +import { ALGORITHM, ALGORITHM_PARAMS, KEY_USAGE } from "../static/subtle.mjs"; + +export const encrypt = async (decrypted) => { + const iv = crypto.getRandomValues(new Uint8Array(16)); + const key = await crypto.subtle.generateKey( + ALGORITHM_PARAMS, + true, + KEY_USAGE + ); + const { k } = await crypto.subtle.exportKey("jwk", key); + const encrypted = await crypto.subtle.encrypt( + { name: ALGORITHM, iv }, + key, + decrypted + ); + + return { iv, k, encrypted }; +}; + +export const create = async (buffer) => { + const { iv, k, encrypted } = await encrypt(buffer); + const uuid = nanoid(22); + + return `${BASE_URL}/${uuid}#${k}`; +}; diff --git a/src/router.js b/src/router.js deleted file mode 100644 index dfb48d8..0000000 --- a/src/router.js +++ /dev/null @@ -1,19 +0,0 @@ -import Router from "@koa/router"; - -export const router = new Router(); - -router.post("/", (ctx, next) => { - if (!ctx.request.rawBody) { - ctx.throw("empty file", 406); - } - - ctx.body = "created"; -}); - -router.get("/", async (ctx, next) => { - await ctx.render("home"); -}); - -router.get("/:id", (ctx, next) => { - ctx.body = ctx.params.id; -}); diff --git a/src/routes.js b/src/routes.js new file mode 100644 index 0000000..8e82f21 --- /dev/null +++ b/src/routes.js @@ -0,0 +1,24 @@ +import Router from "@koa/router"; +import { create } from "./create.js"; + +export const router = new Router(); + +router.post("/", async (ctx, next) => { + if (!ctx.request.rawBody) { + return ctx.throw(406, "empty file"); + } + + const buffer = Buffer.from(ctx.request.rawBody, "binary"); + const url = await create(buffer); + + ctx.status = 201; + ctx.body = `${url}\n`; +}); + +router.get("/", async (ctx, next) => { + await ctx.render("home"); +}); + +router.get("/:id", (ctx, next) => { + ctx.body = ctx.params.id; +});