Skip to content

Commit

Permalink
chore(prisma): Stream Model (#20)
Browse files Browse the repository at this point in the history
---

<details open="true"><summary>Generated summary (powered by <a href="https://app.graphite.dev">Graphite</a>)</summary>

> # Pull Request Description
> 
> ## TL;DR
> This pull request includes changes to a TypeScript file that handles a POST request for a webhook. It verifies the payload, performs different actions based on the event type, and updates the database accordingly. Additionally, it updates the version of "@prisma/client" and makes changes to the prisma schema.
> 
> ## What changed
> - Added a function to handle the POST request for a webhook
> - Added checks for the presence of a webhook secret and required headers
> - Verified the payload using headers and assigned the verified payload to a variable
> - Checked the event type and performed different actions based on the type
> - Modified the conditional statement for the "user.deleted" event type to directly delete a user from the database
> - Updated the version of "@prisma/client" to 5.7.1 in the package.json file
> - Added a new "Stream" field to the "User" model in the prisma schema
> 
> ## How to test
> 1. Run the code snippet in a TypeScript environment
> 2. Send a POST request to the webhook endpoint with the required headers and payload
> 3. Verify that the code handles the request correctly based on the event type
> 4. Check that the database is updated accordingly
> 
> ## Why make this change
> - The code now properly handles the verification of the webhook payload and performs the necessary actions based on the event type.
> - The direct deletion of a user from the database simplifies the code and improves efficiency.
> - Updating the version of "@prisma/client" and making changes to the prisma schema ensures compatibility and adds a new field to the "User" model.
</details>
  • Loading branch information
Zaid-maker authored Dec 21, 2023
2 parents 2d20833 + eb6fe95 commit b1ea94b
Show file tree
Hide file tree
Showing 4 changed files with 131 additions and 109 deletions.
151 changes: 76 additions & 75 deletions app/api/webhooks/clerk/route.ts
Original file line number Diff line number Diff line change
@@ -1,91 +1,92 @@
import { Webhook } from 'svix'
import { headers } from 'next/headers'
import { WebhookEvent } from '@clerk/nextjs/server'
import { db } from '@/lib/db'
import { Webhook } from "svix";
import { headers } from "next/headers";
import { WebhookEvent } from "@clerk/nextjs/server";
import { db } from "@/lib/db";

export async function POST(req: Request) {
// You can find this in the Clerk Dashboard -> Webhooks -> choose the webhook
const WEBHOOK_SECRET = process.env.CLERK_WEBHOOK_SECRET;

// You can find this in the Clerk Dashboard -> Webhooks -> choose the webhook
const WEBHOOK_SECRET = process.env.CLERK_WEBHOOK_SECRET
if (!WEBHOOK_SECRET) {
throw new Error(
"Please add CLERK_WEBHOOK_SECRET from Clerk Dashboard to .env or .env.local"
);
}

if (!WEBHOOK_SECRET) {
throw new Error('Please add CLERK_WEBHOOK_SECRET from Clerk Dashboard to .env or .env.local')
}
// Get the headers
const headerPayload = headers();
const svix_id = headerPayload.get("svix-id");
const svix_timestamp = headerPayload.get("svix-timestamp");
const svix_signature = headerPayload.get("svix-signature");

// Get the headers
const headerPayload = headers();
const svix_id = headerPayload.get("svix-id");
const svix_timestamp = headerPayload.get("svix-timestamp");
const svix_signature = headerPayload.get("svix-signature");
// If there are no headers, error out
if (!svix_id || !svix_timestamp || !svix_signature) {
return new Response("Error occured -- no svix headers", {
status: 400,
});
}

// If there are no headers, error out
if (!svix_id || !svix_timestamp || !svix_signature) {
return new Response('Error occured -- no svix headers', {
status: 400
})
}
// Get the body
const payload = await req.json();
const body = JSON.stringify(payload);

// Get the body
const payload = await req.json()
const body = JSON.stringify(payload);
// Create a new Svix instance with your secret.
const wh = new Webhook(WEBHOOK_SECRET);

// Create a new Svix instance with your secret.
const wh = new Webhook(WEBHOOK_SECRET);
let evt: WebhookEvent;

let evt: WebhookEvent
// Verify the payload with the headers
try {
evt = wh.verify(body, {
"svix-id": svix_id,
"svix-timestamp": svix_timestamp,
"svix-signature": svix_signature,
}) as WebhookEvent;
} catch (err) {
console.error("Error verifying webhook:", err);
return new Response("Error occured", {
status: 400,
});
}

// Verify the payload with the headers
try {
evt = wh.verify(body, {
"svix-id": svix_id,
"svix-timestamp": svix_timestamp,
"svix-signature": svix_signature,
}) as WebhookEvent
} catch (err) {
console.error('Error verifying webhook:', err);
return new Response('Error occured', {
status: 400
})
}
const eventType = evt.type;

const eventType = evt.type;
if (eventType === "user.created") {
await db.user.create({
data: {
externalUserId: payload.data.id,
username: payload.data.username,
imageUrl: payload.data.image_url,
//stream: {
// create: {
// name: `${payload.data.username}'s stream`,
// },
//},
},
});
}

if (eventType === 'user.created') {
await db.user.create({
data: {
externalUserId: payload.data.id,
username: payload.data.username,
imageUrl: payload.data.image_url,
//stream: {
// create: {
// name: `${payload.data.username}'s stream`,
// },
//},
},
})
}
if (eventType === "user.updated") {
await db.user.update({
where: {
externalUserId: payload.data.id,
},
data: {
username: payload.data.username,
imageUrl: payload.data.image_url,
},
});
}

if (eventType === "user.updated") {
await db.user.update({
where: {
externalUserId: payload.data.id,
},
data: {
username: payload.data.username,
imageUrl: payload.data.image_url,
},
});
}
if (eventType === "user.deleted") {
// await resetIngresses(payload.data.id);

if (eventType === "user.deleted") {
// await resetIngresses(payload.data.id);
await db.user.delete({
where: {
externalUserId: payload.data.id,
},
});
}

await db.user.delete({
where: {
externalUserId: payload.data.id,
},
});
}

return new Response('', { status: 200 })
return new Response("", { status: 200 });
}
64 changes: 32 additions & 32 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"dependencies": {
"@clerk/nextjs": "^4.27.7",
"@clerk/themes": "^1.7.9",
"@prisma/client": "^5.7.0",
"@prisma/client": "^5.7.1",
"@radix-ui/react-avatar": "^1.0.4",
"@radix-ui/react-slot": "^1.0.2",
"@radix-ui/react-tooltip": "^1.0.7",
Expand All @@ -38,7 +38,7 @@
"eslint": "^8",
"eslint-config-next": "14.0.4",
"postcss": "^8",
"prisma": "^5.7.0",
"prisma": "^5.7.1",
"tailwindcss": "^3.3.0",
"typescript": "^5"
}
Expand Down
21 changes: 21 additions & 0 deletions prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ model User {
blocking Block[] @relation("Blocking")
blockedBy Block[] @relation("BlockedBy")
Stream Stream?
createAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
Expand All @@ -32,6 +34,25 @@ model Stream {
id String @id @default(uuid())
name String @db.Text
thumbnailUrl String? @db.Text
ingressId String? @unique
serverUrl String? @db.Text
streamKey String? @db.Text
isLive Boolean @default(false)
isChatEnabled Boolean @default(true)
isChatDelayed Boolean @default(false)
isChatFollowersOnly Boolean @default(false)
userId String @unique
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// @@fulltext([name])
@@index([userId])
@@index([ingressId])
}

model Follow {
Expand Down

0 comments on commit b1ea94b

Please sign in to comment.