diff --git a/src/routes/upload.ts b/src/routes/upload.ts index 4981e66..2247c84 100644 --- a/src/routes/upload.ts +++ b/src/routes/upload.ts @@ -8,7 +8,7 @@ import { ValidationError, } from '../errors.js'; import { config } from '../config.js'; -import { save } from '../store.js'; +import { getTakenQuota, save } from '../store.js'; type UploadPayload = { data: string; // base64-encoded diff --git a/src/store.ts b/src/store.ts index e257cea..317e677 100644 --- a/src/store.ts +++ b/src/store.ts @@ -3,14 +3,62 @@ import { config } from './config.js'; import path from 'path'; import fsp from 'node:fs/promises'; +function getClient( + clientName: string, +): { name: string; quota: number } | undefined { + const client = config.clients.find((x) => x.name === clientName) as + | { name: string; quota: number; keySha256Sum?: string } + | undefined; + + delete client?.keySha256Sum; + return client; +} + +function getClientOrThrowErr( + clientName: string, + error?: string, +): { name: string; quota: number } { + const client = getClient(clientName); + if (typeof client === 'undefined') + throw Error(error ?? 'Client does not exist.'); + return client; +} + export function getPathFor(name: string, clientName: string): string { return path.join(config.storePath, clientName + '-' + name); } +export async function getFilesFor(clientName: string): Promise { + const files = await fsp.readdir(config.storePath); + return files.filter((x) => x.startsWith(clientName + '-')); +} + +/** + * @returns { number } In megabytes + */ +export async function getTakenQuota(clientName: string): Promise { + const files = await getFilesFor(clientName); + const stats = await Promise.all( + files.map((x) => fsp.stat(path.join(config.storePath, x))), + ); + + let size = 0; + stats.forEach((x) => (size += x.size)); + + return size / 1000000; +} + export async function save( - data: string | Buffer | NodeJS.ArrayBufferView, + data: Buffer, name: string, clientName: string, -): Promise { +): Promise { + const client = getClientOrThrowErr(clientName); + const quota = await getTakenQuota(clientName); + + if (data.length + quota > client.quota) { + return 'Quota exceeded'; + } + await fsp.writeFile(getPathFor(name, clientName), data); }