fix middleware, migrate gist importing

This commit is contained in:
Max Leiter 2022-11-14 18:39:42 -08:00
parent bc2a4acd29
commit 8e7828d562
19 changed files with 98 additions and 86 deletions

View file

@ -17,7 +17,7 @@ const Description = ({ onChange, description }: props) => {
label="Description" label="Description"
maxLength={256} maxLength={256}
width="100%" width="100%"
placeholder="A short description of your post" placeholder="An optional description of your post"
/> />
</div> </div>
) )

View file

@ -1,6 +1,7 @@
import NewPost from "../../components/new" import NewPost from "../../components/new"
import { notFound } from "next/navigation" import { notFound, redirect } from "next/navigation"
import { getPostById } from "@lib/server/prisma" import { getPostById } from "@lib/server/prisma"
import { getSession } from "@lib/server/session"
const NewFromExisting = async ({ const NewFromExisting = async ({
params params
@ -9,6 +10,11 @@ const NewFromExisting = async ({
id: string id: string
} }
}) => { }) => {
const session = await getSession()
if (!session?.user) {
return redirect("/signin")
}
const { id } = params const { id } = params
if (!id) { if (!id) {

View file

@ -37,10 +37,9 @@ const getPost = async (id: string) => {
return { post, isAuthor: isAuthorOrAdmin } return { post, isAuthor: isAuthorOrAdmin }
} }
// must be authed to see unlisted/private
if ( if (
(post.visibility === "unlisted" || post.visibility === "private") && (post.visibility === "private") &&
!user !isAuthorOrAdmin
) { ) {
return notFound() return notFound()
} }

View file

@ -0,0 +1,11 @@
import { getAllPosts, getAllUsers } from "@lib/server/prisma"
import styles from "./admin.module.css"
import PostTable from "./post-table"
import UserTable from "./user-table"
const Admin = async () => {
)
}
export default Admin

View file

@ -2,15 +2,15 @@
import SettingsGroup from "@components/settings-group" import SettingsGroup from "@components/settings-group"
import { Fieldset, useToasts } from "@geist-ui/core/dist" import { Fieldset, useToasts } from "@geist-ui/core/dist"
import byteToMB from "@lib/byte-to-mb" import byteToMB from "@lib/byte-to-mb"
import { Post } from "@lib/server/prisma"; import { PostWithFiles } from "@lib/server/prisma";
import Table from "rc-table" import Table from "rc-table"
import { useEffect, useMemo, useState } from "react" import { useMemo } from "react"
import ActionDropdown from "./action-dropdown" import ActionDropdown from "./action-dropdown"
const PostTable = ({ const PostTable = ({
posts, posts,
}: { }: {
posts: Post[] posts: PostWithFiles[]
}) => { }) => {
const tablePosts = useMemo( const tablePosts = useMemo(
() => () =>

View file

@ -1,10 +1,7 @@
import type { PostVisibility } from "@lib/types"
import Badge from "../badge" import Badge from "../badge"
type CastPostVisibility = PostVisibility | string
type Props = { type Props = {
visibility: CastPostVisibility visibility: string
} }
const VisibilityBadge = ({ visibility }: Props) => { const VisibilityBadge = ({ visibility }: Props) => {

View file

@ -1,5 +1,4 @@
import { Button, ButtonGroup, Loading, useToasts } from "@geist-ui/core/dist" import { Button, ButtonGroup, Loading, useToasts } from "@geist-ui/core/dist"
import type { PostVisibility } from "@lib/types"
import PasswordModal from "@components/password-modal" import PasswordModal from "@components/password-modal"
import { useCallback, useState } from "react" import { useCallback, useState } from "react"
@ -39,7 +38,7 @@ const VisibilityControl = ({ postId, visibility, setVisibility }: Props) => {
) )
const onSubmit = useCallback( const onSubmit = useCallback(
async (visibility: PostVisibility, password?: string) => { async (visibility: string, password?: string) => {
if (visibility === "protected" && !password) { if (visibility === "protected" && !password) {
setPasswordModalVisible(true) setPasswordModalVisible(true)
return return

View file

@ -10,7 +10,6 @@ import Parent from "@geist-ui/icons/arrowUpCircle"
import styles from "./list-item.module.css" import styles from "./list-item.module.css"
import Link from "@components/link" import Link from "@components/link"
import type { PostWithFiles } from "@lib/server/prisma" import type { PostWithFiles } from "@lib/server/prisma"
import type { PostVisibility } from "@lib/types"
import type { File } from "@lib/server/prisma" import type { File } from "@lib/server/prisma"
import Tooltip from "@components/tooltip" import Tooltip from "@components/tooltip"
import Badge from "@components/badges/badge" import Badge from "@components/badges/badge"
@ -76,7 +75,7 @@ const ListItem = ({
)} )}
<div className={styles.badges}> <div className={styles.badges}>
<VisibilityBadge visibility={post.visibility as PostVisibility} /> <VisibilityBadge visibility={post.visibility} />
<Badge type="secondary"> <Badge type="secondary">
{post.files?.length === 1 {post.files?.length === 1
? "1 file" ? "1 file"

View file

@ -1,7 +1,7 @@
"use client" "use client"
import { Note, Input, Textarea, Button, useToasts } from "@geist-ui/core/dist" import { Note, Input, Textarea, Button, useToasts } from "@geist-ui/core/dist"
import { User } from "@lib/server/prisma" import { User } from "next-auth"
import { useState } from "react" import { useState } from "react"
const Profile = ({ user }: { user: User }) => { const Profile = ({ user }: { user: User }) => {

View file

@ -1,5 +1,3 @@
import fetch from "node-fetch"
import { Response } from "node-fetch"
import { Gist, GistFile } from "./types" import { Gist, GistFile } from "./types"
async function fetchHelper(response: Response): Promise<Response> { async function fetchHelper(response: Response): Promise<Response> {

View file

@ -0,0 +1,68 @@
import { Gist } from "./types"
import * as crypto from "crypto"
import type { Post } from "@lib/server/prisma"
import { getHtmlFromFile } from "@lib/server/get-html-from-drift-file"
import { prisma } from "@lib/server/prisma"
export type AdditionalPostInformation = Pick<
Post,
"visibility" | "password" | "expiresAt"
> & {
userId: string
}
export async function createPostFromGist(
{ userId, visibility, password, expiresAt }: AdditionalPostInformation,
gist: Gist
): Promise<Post> {
const files = Object.values(gist.files)
const [title, description] = gist.description.split("\n", 1)
if (files.length === 0) {
throw new Error("The gist did not have any files")
}
const newPost = await prisma.post.create({
data: {
title,
description,
visibility,
password,
expiresAt,
createdAt: new Date(gist.created_at),
author: {
connect: {
id: userId
}
},
files: {
createMany: {
data: await Promise.all(
files.map(async (file) => {
const content = await file.content()
const html = await getHtmlFromFile({
content,
title: file.filename
})
return {
title: file.filename,
content: content,
sha: crypto
.createHash("sha256")
.update(content)
.digest("hex")
.toString(),
// TODO: shouldn't need this cast
html: html as string,
userId: userId
}
})
)
}
}
}
})
return newPost
}

View file

@ -51,7 +51,7 @@ export const authOptions: NextAuthOptions = {
return { return {
id: dbUser.id, id: dbUser.id,
name: dbUser.username, name: dbUser.displayName,
email: dbUser.email, email: dbUser.email,
picture: dbUser.image, picture: dbUser.image,
role: dbUser.role || "user", role: dbUser.role || "user",

View file

@ -36,7 +36,7 @@ export default withAuth(
) )
export const config = { export const config = {
match: [ matcher: [
// "/signout", // "/signout",
// "/", // "/",
"/signin", "/signin",

0
client/pages/api/gist.ts Normal file
View file

View file

@ -1,65 +0,0 @@
import getHtmlFromFile from "@lib/get-html-from-drift-file"
import { Post } from "@lib/models/Post"
import { File } from "@lib/models/File"
import { Gist } from "./types"
import * as crypto from "crypto"
export type AdditionalPostInformation = Pick<
Post,
"visibility" | "password" | "expiresAt"
> & {
userId: string
}
export async function createPostFromGist(
{ userId, visibility, password, expiresAt }: AdditionalPostInformation,
gist: Gist
): Promise<Post> {
const files = Object.values(gist.files)
const [title, description] = gist.description.split("\n", 1)
if (files.length === 0) {
throw new Error("The gist did not have any files")
}
const newPost = new Post({
title,
description,
visibility,
password,
expiresAt,
createdAt: new Date(gist.created_at)
})
await newPost.save()
await newPost.$add("users", userId)
const newFiles = await Promise.all(
files.map(async (file) => {
const content = await file.content()
const html = getHtmlFromFile({ content, title: file.filename })
const newFile = new File({
title: file.filename,
content,
sha: crypto
.createHash("sha256")
.update(content)
.digest("hex")
.toString(),
html: html || "",
userId: userId,
postId: newPost.id
})
await newFile.save()
return newFile
})
)
await Promise.all(
newFiles.map(async (file) => {
await newPost.$add("files", file.id)
await newPost.save()
})
)
return newPost
}