Skip to content

Commit

Permalink
🚑 Implement clerk webhook
Browse files Browse the repository at this point in the history
  • Loading branch information
mdkaifansari04 committed Jan 9, 2024
1 parent 83b5b83 commit 5394ea7
Show file tree
Hide file tree
Showing 11 changed files with 337 additions and 21 deletions.
11 changes: 3 additions & 8 deletions app/(root)/profile/[userId]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,18 +33,13 @@ const Page = async ({ params }: { params: { userId: string } }) => {
/>
<div className="mt-9">
<Tabs className="w-full" defaultValue="threads">
<TabsList className="tab">
<TabsList className="w-full">
{profileTabs.map((tab) => (
<TabsTrigger
className="flex gap-1"
key={tab.value}
value={tab.value}
>
<TabsTrigger className="tab" key={tab.value} value={tab.value}>
<FadeImg src={tab.icon} className="w-5 h-5" />
<p className="text-dark-2 hidden md:block">{tab.label}</p>
{tab.value === "threads" && userInfo.threads.length > 0 && (
<div className="w-5 h-5 bg-primary text-dark-2 rounded-sm ml-2">
{" "}
<div className="w-5 h-5 bg-primary text-light-1 text-small-medium rounded-sm ml-2">
{userInfo.threads.length}
</div>
)}
Expand Down
63 changes: 63 additions & 0 deletions app/api/webhook/clerk/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { Webhook } from "svix";
import { headers } from "next/headers";
import { WebhookEvent } from "@clerk/nextjs/server";

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

if (!WEBHOOK_SECRET) {
throw new Error(
"Please add 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");

// 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);

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

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,
});
}

// Get the ID and type
const { id } = evt.data;
const eventType = evt.type;

console.log(`Webhook with and ID of ${id} and type of ${eventType}`);
console.log("Webhook body:", body);

if (eventType === "organization.created") {
console.log("Organization created", evt.data);
}

return new Response("", { status: 200 });
}
6 changes: 4 additions & 2 deletions components/cards/threadCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ function ThreadCard({
}: CardProp) {
return (
<article
className={clx(`bg-dark-7 flex flex-row rounded-lg gap-x-3 `, {
className={clx(`bg-dark-7 flex flex-row rounded-xl gap-x-3`, {
"bg-transparent px-5 py-0": isComment,
"p-5": !isComment,
})}
Expand All @@ -56,7 +56,9 @@ function ThreadCard({
<h5 className="cursor-pointer text-base-semibold text-light-1">
{author.name}
</h5>
<p className="mt-2 text-small-regular text-light-2">{content}</p>
<p className="mt-2 text-small-regular text-light-2 tracking-tight leading-5">
{content}
</p>
<div className={`${isComment && "mb-10"} mt-5 flex flex-col gap-3`}>
<div className="flex gap-3.5">
<FadeImg
Expand Down
2 changes: 1 addition & 1 deletion components/ui/tabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const TabsTrigger = React.forwardRef<
<TabsPrimitive.Trigger
ref={ref}
className={clx(
"inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-sm",
"inline-flex items-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-sm !justify-center",
className
)}
{...props}
Expand Down
41 changes: 41 additions & 0 deletions libs/actions/community.actions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { connectToDb } from "../../utils/mongoose";
import Community from "../model/community.model";
import User from "../model/user.model";

interface CommunityCardProps {
name: string;
bio: string;
image: string;
onBoarded?: boolean;
userId: string;
}

export const createCommunity = async (
id: string,
name: string,
bio: string,
image: string,
onBoarded: string,
createdBy: string
) => {
try {
await connectToDb();
const user = await User.findOne({ id: createdBy });
if (!user) return null;

const newCommunity = await Community.create({
name,
bio,
image,
onBoarded,
createdBy,
});

user.community.push(newCommunity._id);
await user.save();

return newCommunity;
} catch (error: any) {
console.log("Failed to create community :", error.message);
}
};
5 changes: 2 additions & 3 deletions libs/actions/user.actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { UserSchema } from "../../interface/schemaType";
import { connectToDb } from "../../utils/mongoose";
import User from "../model/user.model";
import { FilterQuery, SortOrder } from "mongoose";
import Thread from "../model/thread.model";

export const updateUser = async (userData: UserSchema): Promise<void> => {
try {
Expand Down Expand Up @@ -33,7 +32,7 @@ export const updateUser = async (userData: UserSchema): Promise<void> => {
}
};

export const fetchUserById = async (userId: string | null) => {
export const fetchUserById = async (userId: string) => {
try {
await connectToDb();
const user = await User.findOne({ id: userId });
Expand Down Expand Up @@ -64,7 +63,7 @@ export const fetchUsers = async ({
orderBy = "desc",
}: getUserTypeProps) => {
try {
connectToDb();
await connectToDb();

const regex = new RegExp(queryString, "i");
const query: FilterQuery<typeof User> = {
Expand Down
32 changes: 32 additions & 0 deletions libs/model/community.model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import mongoose from "mongoose";

const communitySchema = new mongoose.Schema({
id: {
type: String,
required: true,
},
name: { type: String, required: true },
createdBy: {
type: mongoose.Schema.Types.ObjectId,
ref: "User",
},
bio: String,
image: String,
members: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "User",
},
],
createdAt: { type: Date, default: Date.now() },
onBoarded: {
type: Boolean,
required: true,
default: false,
},
});

const Community =
mongoose.models.Community || mongoose.model("Community", communitySchema);

export default Community;
5 changes: 1 addition & 4 deletions middleware.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
import { authMiddleware } from "@clerk/nextjs";

// This example protects all routes including api/trpc routes
// Please edit this to allow other routes to be public as needed.
// See https://clerk.com/docs/references/nextjs/auth-middleware for more information about configuring your Middleware
export default authMiddleware({
publicRoutes: ["/", "/api/webhook/clerk"],
publicRoutes: ["/", "/api/webhook/clerk", "/api/webhooks(.*)"],
ignoredRoutes: ["/api/webhook/clerk", "/api/uploadthing"],
// debug: true,
});
Expand Down
Loading

0 comments on commit 5394ea7

Please sign in to comment.