not-moddermore/src/routes/create/+page.server.ts
2023-03-06 19:28:26 +09:00

63 lines
2 KiB
TypeScript

import type { Actions } from './$types';
import { COUCHDB_DB_NAME, S3_BUCKET_NAME } from '$env/static/private';
import { fail, redirect } from '@sveltejs/kit';
import { fileTreeSchema } from '$lib/types-zod';
import { get_blobs } from '$lib/utils';
import type { Modpack } from '$lib/types';
import { nanoid } from 'nanoid';
import { minioClient, nano } from '$lib/server/clients';
export const actions: Actions = {
default: async (event) => {
const session = await event.locals.getSession();
if (!session?.user) throw redirect(303, '/auth/signin');
const data = await event.request.formData();
const payload = data.get('payload');
const title = data.get('title');
if (typeof payload != 'string') throw fail(400);
if (typeof title != 'string') throw fail(400);
const payload_decoded = fileTreeSchema.safeParse(JSON.parse(payload));
if (!payload_decoded.success) {
throw fail(400);
}
const blobs = get_blobs(payload_decoded.data);
for (const blob of blobs) {
const file = data.get(blob.sha512);
if (typeof file != 'object' || !file) throw fail(400);
if (file.size > 8 * 1024 * 1024) throw fail(400);
const buf = await file.arrayBuffer();
const hashBuffer = await crypto.subtle.digest('SHA-512', buf);
const hashArray = Array.from(new Uint8Array(hashBuffer));
const hash = hashArray
.map((b) => b.toString(16).padStart(2, '0'))
.join('')
.toLowerCase();
if (hash != blob.sha512) throw fail(400);
let exists = false;
try {
await minioClient.statObject(S3_BUCKET_NAME, blob.sha512);
exists = true;
} catch {
// failed to stat. file doesn't exist
}
if (!exists) {
await minioClient.putObject(S3_BUCKET_NAME, hash, Buffer.from(buf));
}
}
const document: Modpack = {
type: 'modpack',
_id: nanoid(),
name: title,
author: session.user.email ?? 'unknown@nodomain',
revisions: [
{
id: nanoid(),
type: 'base',
tree: payload_decoded.data,
message: 'initial revision'
}
]
};
await nano.use(COUCHDB_DB_NAME).insert(document);
}
};