1
Fork 0
mirror of https://github.com/Steffo99/festa.git synced 2024-12-22 22:54:22 +00:00

this turned out to be pretty clean tbh

This commit is contained in:
Steffo 2022-05-31 12:00:55 +02:00
parent 9f351b1e36
commit 38e2e7b522
Signed by: steffo
GPG key ID: 6965406171929D01
3 changed files with 29 additions and 10 deletions

View file

@ -3,7 +3,7 @@
"version": "0.1.0", "version": "0.1.0",
"private": true, "private": true,
"scripts": { "scripts": {
"dev": "dotenv -e .env.local prisma db push && dotenv -e .env.local prisma generate && dotenv -e .env.local next dev", "dev": "dotenv -e .env.local prisma db push && dotenv -e .env.local prisma generate && NODE_OPTIONS=--inspect dotenv -e .env.local next dev",
"build": "next build", "build": "next build",
"start": "next start", "start": "next start",
"lint": "next lint", "lint": "next lint",

View file

@ -1,17 +1,23 @@
import { client } from "../../../utils/prismaClient"; import { client } from "../../../utils/prismaClient";
import { NextApiRequest, NextApiResponse } from "next"; import { NextApiRequest, NextApiResponse } from "next";
import { ApiResult } from "../../../types/api"; import { ApiResult } from "../../../types/api";
import { restInPeace } from "../../../utils/restInPeace"; import { Model, restInPeace } from "../../../utils/restInPeace";
import { default as cryptoRandomString} from "crypto-random-string"; import { default as cryptoRandomString} from "crypto-random-string";
import { handleInterrupts } from "../../../utils/interrupt"; import { handleInterrupts, Interrupt } from "../../../utils/interrupt";
import { authorizeUser } from "../../../utils/apiAuth"; import { authorizeUser } from "../../../utils/apiAuth";
import { User } from "@prisma/client"; import { Event } from "@prisma/client";
export default async function handler(req: NextApiRequest, res: NextApiResponse<ApiResult<Event | Event[]>>) { export default async function handler(req: NextApiRequest, res: NextApiResponse<ApiResult<Event | Event[]>>) {
handleInterrupts(res, async () => { handleInterrupts(res, async () => {
const user = await authorizeUser(req, res) const user = await authorizeUser(req, res)
const canEdit = async (model: Model, obj?: Event) => {
if(obj && obj.creatorId !== user.id) {
throw new Interrupt(403, {error: "Only the creator can edit an event"})
}
}
const which = { const which = {
slug: req.query.slug slug: req.query.slug
} }
@ -28,7 +34,9 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
model: client.event, model: client.event,
retrieve: {which}, retrieve: {which},
create: {create}, create: {create},
// TODO: this might prove problematic upsert: {create, update, before: canEdit},
update: {update, before: canEdit},
destroy: {before: canEdit},
}) })
}) })
} }

View file

@ -3,7 +3,7 @@ import { ApiError, ApiResult } from "../types/api";
// I don't know what the typing of a Prisma model is. // I don't know what the typing of a Prisma model is.
type Model = any export type Model = any
type RestInPeaceOptions<T> = { type RestInPeaceOptions<T> = {
@ -97,7 +97,7 @@ export async function restInPeace<T>(req: NextApiRequest, res: NextApiResponse<A
interface OperationOptions<T> { interface OperationOptions<T> {
before?: (model: T) => Promise<void>, before?: (model: T, obj?: any) => Promise<void>,
after?: (model: T, obj?: any) => Promise<any>, after?: (model: T, obj?: any) => Promise<any>,
} }
@ -106,6 +106,7 @@ interface OperationOptions<T> {
interface HeadOptions<T> extends OperationOptions<T> { interface HeadOptions<T> extends OperationOptions<T> {
before?: (model: T) => Promise<void>,
after?: (model: T) => Promise<void>, after?: (model: T) => Promise<void>,
} }
@ -123,6 +124,7 @@ async function handleHead<T>(res: NextApiResponse<"">, model: Model, options: He
interface OptionsOptions<T> extends OperationOptions<T> { interface OptionsOptions<T> extends OperationOptions<T> {
before?: (model: T) => Promise<void>,
after?: (model: T) => Promise<void>, after?: (model: T) => Promise<void>,
} }
@ -145,6 +147,7 @@ interface ListOptions<T> extends OperationOptions<T> {
*/ */
where?: object, where?: object,
before?: (model: T) => Promise<void>,
after?: (model: T, obj: T[]) => Promise<T[]>, after?: (model: T, obj: T[]) => Promise<T[]>,
} }
@ -170,6 +173,7 @@ interface RetrieveOptions<T> extends OperationOptions<T> {
*/ */
which?: object, which?: object,
before?: (model: T) => Promise<void>,
after?: (model: T, obj: T) => Promise<T>, after?: (model: T, obj: T) => Promise<T>,
} }
@ -196,6 +200,7 @@ interface CreateOptions<T> extends OperationOptions<T> {
*/ */
create: object, create: object,
before?: (model: T) => Promise<void>,
after?: (model: T, obj: T) => Promise<T>, after?: (model: T, obj: T) => Promise<T>,
} }
@ -231,6 +236,7 @@ interface UpsertOptions<T> extends OperationOptions<T> {
*/ */
update: object, update: object,
before?: (model: T, obj?: T) => Promise<void>,
after?: (model: T, obj: T) => Promise<T>, after?: (model: T, obj: T) => Promise<T>,
} }
@ -238,7 +244,8 @@ interface UpsertOptions<T> extends OperationOptions<T> {
* Handle a `PUT` HTTP request where a single item is either created or updated. * Handle a `PUT` HTTP request where a single item is either created or updated.
*/ */
async function handleUpsert<T>(res: NextApiResponse<ApiResult<T>>, model: Model, options: UpsertOptions<T>) { async function handleUpsert<T>(res: NextApiResponse<ApiResult<T>>, model: Model, options: UpsertOptions<T>) {
await options.before?.(model) const initialObj = await model.findUnique({ where: options.which })
await options.before?.(model, initialObj)
const obj = await model.upsert({ const obj = await model.upsert({
where: options.which, where: options.which,
create: options.create, create: options.create,
@ -265,6 +272,7 @@ interface UpdateOptions<T> extends OperationOptions<T> {
*/ */
update: object, update: object,
before?: (model: T, obj?: T) => Promise<void>,
after?: (model: T, obj: T) => Promise<T>, after?: (model: T, obj: T) => Promise<T>,
} }
@ -272,7 +280,8 @@ interface UpdateOptions<T> extends OperationOptions<T> {
* Handle a `PATCH` HTTP request where a single item is updated. * Handle a `PATCH` HTTP request where a single item is updated.
*/ */
async function handleUpdate<T>(res: NextApiResponse<ApiResult<T>>, model: Model, options: UpdateOptions<T>) { async function handleUpdate<T>(res: NextApiResponse<ApiResult<T>>, model: Model, options: UpdateOptions<T>) {
await options.before?.(model) const initialObj = await model.findUnique({ where: options.which })
await options.before?.(model, initialObj)
const obj = await model.update({ const obj = await model.update({
where: options.which, where: options.which,
data: options.update, data: options.update,
@ -293,6 +302,7 @@ interface DestroyOptions<T> extends OperationOptions<T> {
*/ */
which?: object, which?: object,
before?: (model: T, obj?: T) => Promise<void>,
after?: (model: T) => Promise<void>, after?: (model: T) => Promise<void>,
} }
@ -300,7 +310,8 @@ interface DestroyOptions<T> extends OperationOptions<T> {
* Handle a `DELETE` HTTP request where a single item is destroyed. * Handle a `DELETE` HTTP request where a single item is destroyed.
*/ */
async function handleDestroy<T>(res: NextApiResponse<ApiResult<T>>, model: Model, options: DestroyOptions<T>) { async function handleDestroy<T>(res: NextApiResponse<ApiResult<T>>, model: Model, options: DestroyOptions<T>) {
await options.before?.(model) const initialObj = await model.findUnique({ where: options.which })
await options.before?.(model, initialObj)
await model.delete({ await model.delete({
where: options.which, where: options.which,
}) })