fix raw file viewing, rm password from settings, add admin api
This commit is contained in:
parent
97cff7eb53
commit
0627ab7396
7 changed files with 142 additions and 19 deletions
|
@ -45,10 +45,6 @@
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header .title .badges > * {
|
|
||||||
width: min-content;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header .buttons {
|
.header .buttons {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|
|
@ -29,10 +29,10 @@ const getPost = async (id: string) => {
|
||||||
return notFound()
|
return notFound()
|
||||||
}
|
}
|
||||||
|
|
||||||
const isAuthor = user?.id === post?.authorId
|
const isAuthorOrAdmin = user?.id === post?.authorId || user?.role === "admin"
|
||||||
|
|
||||||
if (post.visibility === "public") {
|
if (post.visibility === "public") {
|
||||||
return { post, isAuthor }
|
return { post, isAuthor: isAuthorOrAdmin }
|
||||||
}
|
}
|
||||||
|
|
||||||
// must be authed to see unlisted/private
|
// must be authed to see unlisted/private
|
||||||
|
@ -43,19 +43,19 @@ const getPost = async (id: string) => {
|
||||||
return notFound()
|
return notFound()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (post.visibility === "private" && !isAuthor) {
|
if (post.visibility === "private" && !isAuthorOrAdmin) {
|
||||||
return notFound()
|
return notFound()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (post.visibility === "protected" && !isAuthor) {
|
if (post.visibility === "protected" && !isAuthorOrAdmin) {
|
||||||
return {
|
return {
|
||||||
post,
|
post,
|
||||||
isProtected: true,
|
isProtected: true,
|
||||||
isAuthor
|
isAuthor: isAuthorOrAdmin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return { post, isAuthor }
|
return { post, isAuthor: isAuthorOrAdmin }
|
||||||
}
|
}
|
||||||
|
|
||||||
const PostView = async ({
|
const PostView = async ({
|
||||||
|
@ -67,8 +67,14 @@ const PostView = async ({
|
||||||
}) => {
|
}) => {
|
||||||
const { post, isProtected, isAuthor } = await getPost(params.id)
|
const { post, isProtected, isAuthor } = await getPost(params.id)
|
||||||
// TODO: serialize dates in prisma middleware instead of passing as JSON
|
// TODO: serialize dates in prisma middleware instead of passing as JSON
|
||||||
const stringifiedPost = JSON.stringify(post);
|
const stringifiedPost = JSON.stringify(post)
|
||||||
return <PostPage isAuthor={isAuthor} isProtected={isProtected} post={stringifiedPost} />
|
return (
|
||||||
|
<PostPage
|
||||||
|
isAuthor={isAuthor}
|
||||||
|
isProtected={isProtected}
|
||||||
|
post={stringifiedPost}
|
||||||
|
/>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// export const getServerSideProps: GetServerSideProps = async ({
|
// export const getServerSideProps: GetServerSideProps = async ({
|
||||||
|
|
|
@ -24,10 +24,7 @@
|
||||||
.badges {
|
.badges {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
}
|
margin-top: var(--gap-half);
|
||||||
|
|
||||||
.badges > * {
|
|
||||||
width: min-content;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
|
|
|
@ -26,9 +26,9 @@ export default async function SettingsPage() {
|
||||||
<SettingsGroup title="Profile">
|
<SettingsGroup title="Profile">
|
||||||
<Profile user={user} />
|
<Profile user={user} />
|
||||||
</SettingsGroup>
|
</SettingsGroup>
|
||||||
<SettingsGroup title="Password">
|
{/* <SettingsGroup title="Password">
|
||||||
<Password />
|
<Password />
|
||||||
</SettingsGroup>
|
</SettingsGroup> */}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ const nextConfig = {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
source: "/file/raw/:id",
|
source: "/file/raw/:id",
|
||||||
destination: `/api/raw/:id`
|
destination: `/api/file/raw/:id`
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
source: "/home",
|
source: "/home",
|
||||||
|
|
121
client/pages/api/admin/index.ts
Normal file
121
client/pages/api/admin/index.ts
Normal file
|
@ -0,0 +1,121 @@
|
||||||
|
// ts nextjs api handler
|
||||||
|
|
||||||
|
import { withMethods } from "@lib/api-middleware/with-methods"
|
||||||
|
import { parseQueryParam } from "@lib/server/parse-query-param"
|
||||||
|
import { NextApiRequest, NextApiResponse } from "next"
|
||||||
|
import { prisma } from "lib/server/prisma"
|
||||||
|
import { getSession } from "next-auth/react"
|
||||||
|
|
||||||
|
const actions = [
|
||||||
|
"user",
|
||||||
|
"post",
|
||||||
|
"users",
|
||||||
|
"posts",
|
||||||
|
"set-role",
|
||||||
|
"delete-user",
|
||||||
|
"delete-post"
|
||||||
|
] as const
|
||||||
|
|
||||||
|
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||||
|
const { action: requestedAction } = req.query
|
||||||
|
const action = parseQueryParam(requestedAction) as typeof actions[number]
|
||||||
|
|
||||||
|
if (!action || !actions.includes(action)) {
|
||||||
|
res.status(400).json({ error: "Invalid action" })
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const session = await getSession({ req })
|
||||||
|
const id = session?.user?.id
|
||||||
|
// get admin from db
|
||||||
|
|
||||||
|
const isAdmin = await prisma.user
|
||||||
|
.findUnique({
|
||||||
|
where: {
|
||||||
|
id
|
||||||
|
},
|
||||||
|
select: {
|
||||||
|
role: true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then((user) => user?.role === "admin")
|
||||||
|
|
||||||
|
if (!isAdmin) {
|
||||||
|
return res.status(403).json({ error: "Not authorized" })
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (req.method) {
|
||||||
|
case "GET":
|
||||||
|
switch (action) {
|
||||||
|
case "users":
|
||||||
|
const users = await prisma.user.findMany()
|
||||||
|
return res.status(200).json(users)
|
||||||
|
case "posts":
|
||||||
|
const posts = await prisma.post.findMany()
|
||||||
|
return res.status(200).json(posts)
|
||||||
|
case "user":
|
||||||
|
const { id: userId } = req.query
|
||||||
|
const user = await prisma.user.findUnique({
|
||||||
|
where: {
|
||||||
|
id: parseQueryParam(userId)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return res.status(200).json(user)
|
||||||
|
case "post":
|
||||||
|
const { id: postId } = req.query
|
||||||
|
const post = await prisma.post.findUnique({
|
||||||
|
where: {
|
||||||
|
id: parseQueryParam(postId)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return res.status(200).json(post)
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case "PATCH":
|
||||||
|
switch (action) {
|
||||||
|
case "set-role":
|
||||||
|
const { userId, role } = req.body
|
||||||
|
if (!userId || !role || role !== "admin" || role !== "user") {
|
||||||
|
return res.status(400).json({ error: "Invalid request" })
|
||||||
|
}
|
||||||
|
|
||||||
|
const user = await prisma.user.update({
|
||||||
|
where: { id: userId },
|
||||||
|
data: {
|
||||||
|
role: role
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return res.status(200).json(user)
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case "DELETE":
|
||||||
|
switch (action) {
|
||||||
|
case "delete-user":
|
||||||
|
const { userId } = req.body
|
||||||
|
if (!userId) {
|
||||||
|
return res.status(400).json({ error: "Invalid request" })
|
||||||
|
}
|
||||||
|
|
||||||
|
const user = await prisma.user.delete({
|
||||||
|
where: { id: userId }
|
||||||
|
})
|
||||||
|
|
||||||
|
return res.status(200).json(user)
|
||||||
|
case "delete-post":
|
||||||
|
const { postId } = req.body
|
||||||
|
if (!postId) {
|
||||||
|
return res.status(400).json({ error: "Invalid request" })
|
||||||
|
}
|
||||||
|
|
||||||
|
const post = await prisma.post.delete({
|
||||||
|
where: { id: postId }
|
||||||
|
})
|
||||||
|
|
||||||
|
return res.status(200).json(post)
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default withMethods(["GET", "PATCH", "DELETE"], handler)
|
|
@ -141,6 +141,9 @@ async function handleDelete(req: NextApiRequest, res: NextApiResponse<any>) {
|
||||||
await prisma.post.delete({
|
await prisma.post.delete({
|
||||||
where: {
|
where: {
|
||||||
id
|
id
|
||||||
|
},
|
||||||
|
include: {
|
||||||
|
files: true
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue