مقدمه
ساختن پنل ادمین یعنی تصمیم بگیرید چه کسی چه چیزی را ببیند یا انجام بدهد. یک رویکرد استاتیک ساده — نقشها و دسترسیها داخل کد و نه از API — برای پروژههای کوچک/متوسط کافی است. این الگو نشان میدهد چطور هم روتها و هم کنترلهای UI را نگه دارید و بعداً اگر خواستید پویا کنید، آماده باشید.
چی را پوشش میدهیم
- تعریف نقشها، صفحات و دسترسیها در یک جا
- محافظت از روتها تا فقط نقشهای مجاز وارد شوند
- نمایش یا پنهانکردن اکشنهای UI بر اساس دسترسی
۱) تعریف نقشها و دسترسیها
همهچیز را در یک roles.ts نگه دارید تا منطق پخش نشود.
// roles.ts
export const ROLES = {
ADMIN: "ADMIN",
EDITOR: "EDITOR",
VIEWER: "VIEWER",
} as const;
export const PERMISSIONS = {
USER_CREATE: "USER_CREATE",
USER_DELETE: "USER_DELETE",
USER_VIEW: "USER_VIEW",
} as const;
export const roleAccess = {
[ROLES.ADMIN]: ["dashboard", "users", "settings"],
[ROLES.EDITOR]: ["dashboard", "users"],
[ROLES.VIEWER]: ["dashboard"],
};
export const rolePermissions = {
[ROLES.ADMIN]: [
PERMISSIONS.USER_CREATE,
PERMISSIONS.USER_DELETE,
PERMISSIONS.USER_VIEW,
],
[ROLES.EDITOR]: [PERMISSIONS.USER_VIEW],
[ROLES.VIEWER]: [PERMISSIONS.USER_VIEW],
};
این میشود منبع واحد: هر نقش به کدام صفحه میرود و چه اکشنی میتواند انجام دهد.
۲) کنترل سطح روت با ProtectedRoute
اگر نقش کاربر مجاز نیست، اجازهٔ ورود به صفحه ندهید.
// ProtectedRoute.tsx
import { Navigate } from "react-router-dom";
import { useAuth } from "@/hooks/useAuth";
import { roleAccess, ROLES } from "./roles";
export function ProtectedRoute({
children,
allowed,
}: {
children: JSX.Element;
allowed: string[];
}) {
const { role } = useAuth();
if (!role || !allowed.includes(role)) {
return <Navigate to="/unauthorized" replace />;
}
return children;
}
در تنظیمات روت استفاده کنید:
// routes.tsx
import { ProtectedRoute } from "./ProtectedRoute";
import { roleAccess, ROLES } from "./roles";
import DashboardPage from "@/features/dashboard/pages/DashboardPage";
import UsersPage from "@/features/users/pages/UsersPage";
export const routes = [
{
path: "/dashboard",
element: (
<ProtectedRoute allowed={roleAccess[ROLES.VIEWER]}>
<DashboardPage />
</ProtectedRoute>
),
},
{
path: "/users",
element: (
<ProtectedRoute allowed={roleAccess[ROLES.EDITOR]}>
<UsersPage />
</ProtectedRoute>
),
},
];
فقط نقشهایی که در roleAccess آمدهاند به صفحه میرسند.
۳) کنترل سطح کامپوننت با AccessControl
اکشنهای UI را بر اساس دسترسی نشان دهید یا پنهان کنید.
// AccessControl.tsx
import { ReactNode } from "react";
import { useAuth } from "@/hooks/useAuth";
import { rolePermissions } from "./roles";
type Props = {
permission: string;
children: ReactNode;
};
export function AccessControl({ permission, children }: Props) {
const { role } = useAuth();
if (!role) return null;
const permissions = rolePermissions[role] || [];
return permissions.includes(permission) ? <>{children}</> : null;
}
نمونهٔ استفاده داخل صفحه:
import { AccessControl } from "@/components/AccessControl";
import { PERMISSIONS } from "@/routes/roles";
function UsersPage() {
return (
<div>
<h1>User List</h1>
<AccessControl permission={PERMISSIONS.USER_CREATE}>
<button>Add User</button>
</AccessControl>
<AccessControl permission={PERMISSIONS.USER_DELETE}>
<button>Delete User</button>
</AccessControl>
</div>
);
}
خلاصه
- نقشها، روتها و دسترسیها را در یک ماژول (
roles.ts) نگه دارید. - با
ProtectedRouteناوبری را امن کنید. - با
AccessControlاکشنهای UI را محدود کنید. - از استاتیک شروع کنید؛ بعداً میتوانید
roleAccessوrolePermissionsرا با دادهٔ API عوض کنید.
جمعبندی
با چند کمککنندهٔ سبک، کنترل دسترسی متمرکز و قابل پیشبینی دارید؛ هم برای امروز تمیز است و هم فردا میتوانید به نسخهٔ داینامیک مهاجرت کنید. کدنویسیتان پرانرژی! 🚀