Switch post html/content to Bytes from Text

This commit is contained in:
Max Leiter 2022-12-17 17:15:21 -08:00
parent 34a92a265f
commit 69c482a165
7 changed files with 114 additions and 67 deletions

View file

@ -151,7 +151,7 @@ const Post = ({
setSubmitting(false)
return
}
await sendRequest("/api/post", {
title,
files: docs,

View file

@ -47,14 +47,13 @@ export async function createPostFromGist(
return {
title: file.filename,
content: content,
content: Buffer.from(content, "utf-8"),
sha: crypto
.createHash("sha256")
.update(content)
.digest("hex")
.toString(),
// TODO: shouldn't need this cast
html: html as string,
html: Buffer.from(html as string, "utf-8"),
userId: userId
}
})

View file

@ -1,4 +1,3 @@
import type { File } from "@lib/server/prisma"
import markdown from "@wcj/markdown-to-html"
/**
* returns rendered HTML from a Drift file
@ -6,7 +5,10 @@ import markdown from "@wcj/markdown-to-html"
export async function getHtmlFromFile({
content,
title
}: Pick<File, "content" | "title">) {
}: {
content: string
title: string
}) {
const renderAsMarkdown = [
"markdown",
"md",

View file

@ -36,12 +36,44 @@ if (config.enable_admin) {
if (process.env.NODE_ENV !== "production") global.prisma = prisma
export type PostWithFiles = Post & {
files: File[]
const postWithFiles = Prisma.validator<Prisma.PostArgs>()({
include: {
files: true
}
})
const postWithAuthor = Prisma.validator<Prisma.PostArgs>()({
include: {
author: true
}
})
const postWithFilesAndAuthor = Prisma.validator<Prisma.PostArgs>()({
include: {
files: true,
author: true
}
})
export type ServerPostWithFiles = Prisma.PostGetPayload<typeof postWithFiles>
export type PostWithAuthor = Prisma.PostGetPayload<typeof postWithAuthor>
export type ServerPostWithFilesAndAuthor = Prisma.PostGetPayload<typeof postWithFilesAndAuthor>
export type PostWithFiles = Omit<ServerPostWithFiles, "files"> & {
files: Omit<ServerPostWithFiles["files"][number], "content" | "html"> & {
content: string
html: string
}[]
}
export type PostWithFilesAndAuthor = PostWithFiles & {
author: User
export type PostWithFilesAndAuthor = Omit<
ServerPostWithFilesAndAuthor,
"files"
> & {
files: Omit<ServerPostWithFilesAndAuthor["files"][number], "content" | "html"> & {
content: string
html: string
}[]
}
export const getFilesForPost = async (postId: string) => {
@ -68,7 +100,7 @@ export async function getPostsByUser(userId: string): Promise<Post[]>
export async function getPostsByUser(
userId: string,
includeFiles: true
): Promise<PostWithFiles[]>
): Promise<ServerPostWithFiles[]>
export async function getPostsByUser(userId: User["id"], withFiles?: boolean) {
const posts = await prisma.post.findMany({
where: {
@ -148,13 +180,26 @@ export const getPostById = async (
postId: Post["id"],
options?: GetPostByIdOptions
): Promise<Post | PostWithFiles | PostWithFilesAndAuthor | null> => {
const post = await prisma.post.findUnique({
let post = await prisma.post.findUnique({
where: {
id: postId
},
...options
})
if (post) {
if ("files" in post) {
// @ts-expect-error TODO: fix types so files can exist
console.log(post.files)
// @ts-expect-error TODO: fix types so files can exist
post.files = post.files.map((file) => ({
...file,
content: file.content ? file.content.toString() : undefined,
html: file.html ? file.html.toString() : undefined
}))
}
}
return post
}
@ -167,7 +212,7 @@ export const getAllPosts = async ({
withFiles?: boolean
withAuthor?: boolean
} & Prisma.PostFindManyArgs = {}): Promise<
Post[] | PostWithFiles[] | PostWithFilesAndAuthor[]
Post[] | ServerPostWithFiles[] | ServerPostWithFilesAndAuthor[]
> => {
const posts = await prisma.post.findMany({
include: {
@ -216,7 +261,7 @@ export const searchPosts = async (
userId?: User["id"]
publicOnly?: boolean
} = {}
): Promise<PostWithFiles[]> => {
): Promise<ServerPostWithFiles[]> => {
const posts = await prisma.post.findMany({
where: {
OR: [
@ -231,9 +276,8 @@ export const searchPosts = async (
files: {
some: {
content: {
search: query
},
userId: userId
in: Buffer.from(query)
}
}
},
visibility: publicOnly ? "public" : undefined
@ -245,5 +289,5 @@ export const searchPosts = async (
}
})
return posts as PostWithFiles[]
return posts as ServerPostWithFiles[]
}

View file

@ -1,6 +1,6 @@
import { withMethods } from "@lib/api-middleware/with-methods"
import { parseQueryParam } from "@lib/server/parse-query-param"
import { getPostById } from "@lib/server/prisma"
import { getPostById, PostWithFiles } from "@lib/server/prisma"
import type { NextApiRequest, NextApiResponse } from "next"
import { getSession } from "next-auth/react"
import { prisma } from "lib/server/prisma"
@ -16,7 +16,6 @@ export default withMethods(["GET", "PUT", "DELETE"], handler)
async function handleGet(req: NextApiRequest, res: NextApiResponse<any>) {
const id = parseQueryParam(req.query.id)
const files = req.query.files ? parseQueryParam(req.query.files) : true
if (!id) {
return res.status(400).json({ error: "Missing id" })
@ -44,7 +43,9 @@ async function handleGet(req: NextApiRequest, res: NextApiResponse<any>) {
// the user can always go directly to their own post
if (session?.user.id === post.authorId) {
return res.json(post)
return res.json({
...post,
})
}
if (post.visibility === "protected") {
@ -56,7 +57,9 @@ async function handleGet(req: NextApiRequest, res: NextApiResponse<any>) {
.toString()
if (hash === post.password) {
return res.json(post)
return res.json({
...post,
})
} else {
return {
isProtected: true,

View file

@ -3,7 +3,7 @@
import { withMethods } from "@lib/api-middleware/with-methods"
import { authOptions } from "@lib/server/auth"
import {prisma, getPostById } from "@lib/server/prisma"
import { prisma, getPostById } from "@lib/server/prisma"
import { NextApiRequest, NextApiResponse } from "next"
import { unstable_getServerSession } from "next-auth/next"
import { File } from "@lib/server/prisma"
@ -25,7 +25,7 @@ async function handlePost(req: NextApiRequest, res: NextApiResponse<any>) {
return res.status(401).json({ error: "Unauthorized" })
}
const files = req.body.files as File[]
const files = req.body.files as Omit<File, 'content' | 'html'> & { content: string; html: string; }[]
const fileTitles = files.map((file) => file.title)
const missingTitles = fileTitles.filter((title) => title === "")
if (missingTitles.length > 0) {
@ -44,52 +44,51 @@ async function handlePost(req: NextApiRequest, res: NextApiResponse<any>) {
.digest("hex")
}
const post = await prisma.post.create({
data: {
title: req.body.title,
description: req.body.description,
visibility: req.body.visibility,
password: hashedPassword,
expiresAt: req.body.expiresAt,
parentId: req.body.parentId,
authorId: session.user.id,
// files: {
// connectOrCreate: postFiles.map((file) => ({
// where: {
// sha: file.sha
// },
// create: file
// }))
// }
}
})
await Promise.all(
const fileHtml = await Promise.all(
files.map(async (file) => {
const html = (await getHtmlFromFile(file)) as string
return prisma.file.create({
data: {
title: file.title,
content: file.content,
sha: crypto
.createHash("sha256")
.update(file.content)
.digest("hex")
.toString(),
html: html,
userId: session.user.id,
post: {
connect: {
id: post.id
}
}
}
return await getHtmlFromFile({
content: file.content,
title: file.title
})
})
)
const post = await prisma.post
.create({
data: {
title: req.body.title,
description: req.body.description,
visibility: req.body.visibility,
password: hashedPassword,
expiresAt: req.body.expiresAt,
parentId: req.body.parentId,
authorId: session.user.id,
files: {
create: files.map((file) => {
console.log(file)
return {
title: file.title,
content: Buffer.from(file.content, "utf-8"),
sha: crypto
.createHash("sha256")
.update(file.content)
.digest("hex")
.toString(),
html: Buffer.from(
fileHtml[files.indexOf(file)] as string,
"utf-8"
),
userId: session.user.id
}
})
}
}
})
.catch((error) => {
console.log(error)
return res.status(500).json(error)
})
return res.json(post)
} catch (error) {
return res.status(500).json(error)

View file

@ -16,9 +16,9 @@ model SequelizeMeta {
model File {
id String @id @default(cuid())
title String
content String
content Bytes
sha String
html String
html Bytes
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
deletedAt DateTime?