جاري التحميل...
جاري التحميل...
UserButton، useUser، useAuth، currentUser، clerkClient
يقدم Clerk عدة ميزات متقدمة تعزز الأمان وتجربة المستخدم.
// middleware.js
import { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server';
const isPublicRoute = createRouteMatcher(['/sign-in(.*)', '/sign-up(.*)', '/']);
export default clerkMiddleware(async (req, auth) => {
if (!isPublicRoute(req)) {
await auth.protect();
}
});
export const config = [
'/((?!_next|[^?]*\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)).*)',
'/(api|trpc)(.*)',
];استخدم Clerk للمصادقة و Supabase لقاعدة البيانات. أرسل رمز JWT من Clerk إلى Supabase للتحقق من المستخدمين.
// الحصول على رمز Clerk لـ Supabase
import { auth } from '@clerk/nextjs/server';
export async function getSupabaseUser() {
const { userId } = await auth();
// استخدم userId للاستعلام من Supabase
}يمكن تسمية مكونات Clerk باستخدام أنساق Tailwind CSS أو خاصية appearance.
<SignIn
appearance={{
elements: {
rootBox: 'mx-auto',
card: 'shadow-xl rounded-lg',
},
}}
/>ماذا يفعل clerkMiddleware؟
كيف تخصيص مظهر مكونات Clerk؟
نفذ middleware.js لحماية جميع المسارات ما عدا العامة. أضف سمة مخصصة لمكون تسجيل الدخول.
الحل:
"use client";
import { useUser, useAuth, useSessionList } from "@clerk/nextjs";
import { UserProfile } from "@clerk/nextjs";
export default function ProfilePage() {
const { user, isLoaded } = useUser();
const { has, signOut } = useAuth();
const { sessions } = useSessionList();
if (!isLoaded) {
return <div>جاري التحميل...</div>;
}
return (
<div dir="rtl" className="min-h-screen bg-gray-50 py-8">
<div className="max-w-4xl mx-auto px-4">
<h1 className="text-2xl font-bold mb-6">الملف الشخصي</h1>
{/* معلومات المستخدم */}
<div className="bg-white p-6 rounded-lg shadow mb-6">
<div className="flex items-center gap-4">
<img
src={user?.imageUrl}
alt={user?.fullName}
className="w-16 h-16 rounded-full"
/>
<div>
<h2 className="text-xl font-bold">{user?.fullName}</h2>
<p className="text-gray-500">
{user?.primaryEmailAddress?.emailAddress}
</p>
</div>
</div>
</div>
{/* الصلاحيات */}
<div className="bg-white p-6 rounded-lg shadow mb-6">
<h3 className="font-bold mb-3">الصلاحيات</h3>
<div className="flex gap-2">
{has({ role: "org:admin" }) && (
<span className="bg-purple-100 text-purple-800 px-3 py-1 rounded-full text-sm">
مدير
</span>
)}
{has({ role: "org:teacher" }) && (
<span className="bg-blue-100 text-blue-800 px-3 py-1 rounded-full text-sm">
معلم
</span>
)}
{has({ role: "org:student" }) && (
<span className="bg-green-100 text-green-800 px-3 py-1 rounded-full text-sm">
طالب
</span>
)}
</div>
</div>
{/* الجلسات */}
<div className="bg-white p-6 rounded-lg shadow mb-6">
<h3 className="font-bold mb-3">الجلسات النشطة</h3>
<div className="space-y-2">
{sessions?.map((session) => (
<div
key={session.id}
className="flex justify-between items-center p-3 bg-gray-50 rounded-lg"
>
<div>
<p className="font-medium">
{session.user?.fullName}
</p>
<p className="text-sm text-gray-500">
آخر نشاط: {session.lastActiveAt?.toLocaleDateString("ar-SA")}
</p>
</div>
{session.current && (
<span className="text-xs bg-green-100 text-green-800 px-2 py-1 rounded">
حالية
</span>
)}
</div>
))}
</div>
</div>
{/* زر تسجيل الخروج */}
<button
onClick={() => signOut()}
className="w-full bg-red-600 text-white py-3 rounded-lg hover:bg-red-700"
>
تسجيل الخروج
</button>
</div>
</div>
);
}المكونات:
{" "} - صورة المستخدم مع قائمة منسدلة{" "} - صفحة إدارة الملف الشخصي الكاملةخطافات العميل:
useUser() - user, isLoaded, isSignedInuseAuth() - userId, sessionId, getToken, signOut, hasuseSession() - معلومات الجلسة الحاليةuseSessionList() - جميع الجلسات النشطةالإجابة:
استخدم auth() في Server Components
للتحقق من المستخدم في Server Components مباشرة