feat: add RBAC permission system to admin cabinet frontend

- Permission store (Zustand) with wildcard matching and role level checks
- PermissionRoute guard for route-level access control
- PermissionGate component for element-level visibility
- Admin Roles page: CRUD, permission editor, role assignment
- Admin Policies page: ABAC policy management (time/IP conditions)
- Admin Audit Log page: filterable log viewer with CSV export
- AdminPanel sidebar navigation gated by permissions
- 4 locale files updated (en, ru, zh, fa) with RBAC translations
- API client module for all RBAC endpoints
This commit is contained in:
Fringg
2026-02-25 03:02:52 +03:00
parent 48be067d1b
commit 874ee2682e
15 changed files with 5320 additions and 121 deletions

View File

@@ -835,7 +835,8 @@
"marketing": "Marketing",
"system": "System",
"tariffs": "Tariffs & Sales",
"users": "Users"
"users": "Users",
"security": "Security"
},
"nav": {
"title": "Admin",
@@ -862,7 +863,11 @@
"pinnedMessages": "Pinned Messages",
"partners": "Partners",
"withdrawals": "Withdrawals",
"channelSubscriptions": "Required Channels"
"channelSubscriptions": "Required Channels",
"roles": "Roles",
"roleAssign": "Role Assignment",
"policies": "Access Policies",
"auditLog": "Audit Log"
},
"panel": {
"title": "Admin Panel",
@@ -890,7 +895,11 @@
"pinnedMessagesDesc": "Manage pinned messages for users",
"partnersDesc": "Manage partner applications and commissions",
"withdrawalsDesc": "Review and process withdrawal requests",
"channelSubscriptionsDesc": "Manage required channel subscriptions"
"channelSubscriptionsDesc": "Manage required channel subscriptions",
"rolesDesc": "Manage admin roles and permissions",
"roleAssignDesc": "Assign and revoke user roles",
"policiesDesc": "Configure ABAC access policies",
"auditLogDesc": "Review system activity and access history"
},
"trafficUsage": {
"title": "Traffic Usage",
@@ -2920,6 +2929,274 @@
"unhealthy": "Unhealthy",
"components": "Components",
"uptime": "Uptime"
},
"roles": {
"title": "Roles & Permissions",
"subtitle": "Manage admin roles and their permissions",
"createRole": "Create Role",
"noRoles": "No roles found",
"systemBadge": "System",
"inactiveBadge": "Inactive",
"levelLabel": "Level",
"usersCount_one": "{{count}} user",
"usersCount_other": "{{count}} users",
"permissionsCount_one": "{{count}} permission",
"permissionsCount_other": "{{count}} permissions",
"stats": {
"totalRoles": "Total roles",
"active": "Active",
"system": "System"
},
"actions": {
"edit": "Edit",
"delete": "Delete"
},
"modal": {
"createTitle": "Create Role",
"editTitle": "Edit Role",
"close": "Close"
},
"form": {
"name": "Role name",
"namePlaceholder": "e.g. Moderator",
"description": "Description",
"descriptionPlaceholder": "What this role is for...",
"level": "Priority level",
"levelValue": "Level value",
"levelHint": "Higher level = more authority. Users can only manage roles with a lower level than their own.",
"color": "Color",
"presets": "Permission presets",
"permissions": "Permissions",
"toggleSection": "Toggle all {{section}} permissions",
"selectedPermissions_one": "{{count}} permission selected",
"selectedPermissions_other": "{{count}} permissions selected",
"cancel": "Cancel",
"saving": "Saving...",
"save": "Save"
},
"presets": {
"moderator": "Moderator",
"marketer": "Marketer",
"support": "Support"
},
"confirm": {
"title": "Delete role?",
"text": "This role will be permanently deleted. Users with this role will lose its permissions.",
"cancel": "Cancel",
"delete": "Delete",
"deleting": "Deleting..."
},
"errors": {
"loadFailed": "Failed to load roles",
"createFailed": "Failed to create role",
"updateFailed": "Failed to update role",
"nameRequired": "Role name is required"
}
},
"roleAssign": {
"title": "Role Assignment",
"subtitle": "Assign and manage user roles",
"assignSection": "Assign Role",
"userLabel": "User",
"searchPlaceholder": "Search by name, username, Telegram ID, or email...",
"clearUser": "Clear selected user",
"noUsersFound": "No users found",
"roleLabel": "Role",
"selectRole": "Select a role...",
"expiresLabel": "Expires at (optional)",
"expiresHint": "Leave empty for permanent assignment",
"assignButton": "Assign",
"assigning": "Assigning...",
"assignSuccess": "Role assigned successfully",
"currentAssignments": "Current Assignments",
"totalAssignments_one": "{{count}} assignment total",
"totalAssignments_other": "{{count}} assignments total",
"noAssignments": "No role assignments found",
"unknownUser": "Unknown user",
"system": "System",
"permanent": "Permanent",
"expired": "expired",
"revoke": "Revoke",
"revokeAriaLabel": "Revoke role {{role}} from {{user}}",
"table": {
"user": "User",
"role": "Role",
"assignedBy": "Assigned by",
"assignedAt": "Assigned at",
"expires": "Expires",
"actions": "Actions"
},
"pagination": {
"showing": "{{from}}-{{to}} of {{total}}",
"prev": "Previous page",
"next": "Next page"
},
"confirm": {
"title": "Revoke role?",
"text": "This user will immediately lose all permissions associated with this role.",
"cancel": "Cancel",
"revoke": "Revoke",
"revoking": "Revoking..."
},
"errors": {
"userRequired": "Please select a user",
"roleRequired": "Please select a role",
"assignFailed": "Failed to assign role"
}
},
"policies": {
"title": "Access Policies",
"subtitle": "Manage ABAC access control policies",
"createPolicy": "Create Policy",
"noPolicies": "No policies found",
"inactiveBadge": "Inactive",
"effectAllow": "Allow",
"effectDeny": "Deny",
"global": "Global",
"unknownRole": "Unknown role",
"roleLabel": "Role",
"priorityLabel": "Priority",
"stats": {
"total": "Total policies",
"allow": "Allow",
"deny": "Deny",
"active": "Active"
},
"actions": {
"edit": "Edit",
"delete": "Delete"
},
"modal": {
"createTitle": "Create Policy",
"editTitle": "Edit Policy",
"close": "Close"
},
"form": {
"name": "Policy name",
"namePlaceholder": "e.g. Block night access",
"description": "Description",
"descriptionPlaceholder": "What this policy does...",
"effect": "Effect",
"resource": "Resource",
"selectResource": "Select a resource...",
"actions": "Actions",
"role": "Role (optional)",
"globalOption": "Global (all roles)",
"roleHint": "Leave as Global to apply the policy to all roles.",
"priority": "Priority",
"priorityHint": "Higher priority policies are evaluated first. Deny overrides Allow at equal priority.",
"conditions": "Conditions",
"cancel": "Cancel",
"saving": "Saving...",
"save": "Save"
},
"conditions": {
"timeRange": "Time range",
"timeStart": "Start time",
"timeEnd": "End time",
"ipWhitelist": "IP whitelist",
"ipPlaceholder": "Enter IP and press Enter...",
"removeIp": "Remove {{ip}}",
"ipCount_one": "{{count}} IP",
"ipCount_other": "{{count}} IPs",
"rateLimit": "Rate limit",
"rateLimitValue": "Rate limit value",
"rateValue": "{{count}}/hr",
"perHour": "actions per hour"
},
"confirm": {
"title": "Delete policy?",
"text": "This policy will be permanently deleted. Access control rules will be recalculated.",
"cancel": "Cancel",
"delete": "Delete",
"deleting": "Deleting..."
},
"errors": {
"loadFailed": "Failed to load policies",
"createFailed": "Failed to create policy",
"updateFailed": "Failed to update policy",
"nameRequired": "Policy name is required",
"resourceRequired": "Please select a resource",
"actionsRequired": "Please select at least one action"
}
},
"auditLog": {
"title": "Audit Log",
"subtitle": "Review system activity and access history",
"back": "Back",
"exportCsv": "Export CSV",
"exporting": "Exporting...",
"refresh": "Refresh",
"unknownUser": "Unknown user",
"noEntries": "No audit log entries found",
"totalEntries_one": "{{count}} entry",
"totalEntries_other": "{{count}} entries",
"autoRefresh": {
"label": "Auto-refresh",
"tooltip": "Auto-refresh every 30 seconds"
},
"filters": {
"title": "Filters",
"active": "Active",
"action": "Action",
"actionPlaceholder": "Search by action...",
"resource": "Resource type",
"allResources": "All resources",
"status": "Status",
"allStatuses": "All statuses",
"dateFrom": "Date from",
"dateTo": "Date to",
"apply": "Apply",
"clear": "Clear"
},
"status": {
"success": "Success",
"denied": "Denied",
"error": "Error"
},
"resourceTypes": {
"users": "Users",
"tickets": "Tickets",
"roles": "Roles",
"policies": "Policies",
"settings": "Settings",
"broadcasts": "Broadcasts",
"tariffs": "Tariffs",
"servers": "Servers",
"payments": "Payments",
"campaigns": "Campaigns",
"promocodes": "Promo Codes"
},
"details": {
"userAgent": "User Agent",
"requestPath": "Request Path",
"ipAddress": "IP Address",
"timestamp": "Timestamp",
"before": "Before",
"after": "After",
"fullDetails": "Full Details"
},
"time": {
"justNow": "Just now",
"minutesAgo_one": "{{count}} min ago",
"minutesAgo_other": "{{count}} min ago",
"hoursAgo_one": "{{count}} hr ago",
"hoursAgo_other": "{{count}} hrs ago",
"daysAgo_one": "{{count}} day ago",
"daysAgo_other": "{{count}} days ago"
},
"pagination": {
"pageSize": "Per page:",
"pageOf": "{{current}} / {{total}}",
"first": "First page",
"previous": "Previous page",
"next": "Next page",
"last": "Last page"
},
"errors": {
"loadFailed": "Failed to load audit log",
"retry": "Try again"
}
}
},
"profile": {

View File

@@ -742,7 +742,11 @@
"pinnedMessages": "پیام‌های سنجاق‌شده",
"partners": "شرکا",
"withdrawals": "برداشت‌ها",
"channelSubscriptions": "کانال‌های اجباری"
"channelSubscriptions": "کانال‌های اجباری",
"roles": "نقش‌ها",
"roleAssign": "تخصیص نقش",
"policies": "سیاست‌های دسترسی",
"auditLog": "گزارش بازرسی"
},
"panel": {
"title": "پنل مدیریت",
@@ -770,7 +774,11 @@
"pinnedMessagesDesc": "مدیریت پیام‌های سنجاق‌شده",
"partnersDesc": "مدیریت درخواست‌های شراکت و کمیسیون‌ها",
"withdrawalsDesc": "بررسی و پردازش درخواست‌های برداشت",
"channelSubscriptionsDesc": "مدیریت اشتراک‌های اجباری کانال"
"channelSubscriptionsDesc": "مدیریت اشتراک‌های اجباری کانال",
"rolesDesc": "مدیریت نقش‌ها و مجوزهای مدیران",
"roleAssignDesc": "تخصیص و لغو نقش‌های کاربران",
"policiesDesc": "تنظیم سیاست‌های کنترل دسترسی ABAC",
"auditLogDesc": "بررسی فعالیت سیستم و تاریخچه دسترسی"
},
"trafficUsage": {
"title": "مصرف ترافیک",
@@ -2202,7 +2210,8 @@
"marketing": "بازاریابی",
"system": "سیستم",
"tariffs": "تعرفه‌ها و فروش",
"users": "کاربران"
"users": "کاربران",
"security": "امنیت"
},
"remnawave": {
"connected": "متصل",
@@ -2783,6 +2792,265 @@
"node": "گره",
"requests": "درخواست‌ها",
"ipHistory": "تاریخچه IP"
},
"roles": {
"title": "نقش‌ها و مجوزها",
"subtitle": "مدیریت نقش‌های مدیران و مجوزهای آن‌ها",
"createRole": "ایجاد نقش",
"noRoles": "نقشی یافت نشد",
"systemBadge": "سیستمی",
"inactiveBadge": "غیرفعال",
"levelLabel": "سطح",
"usersCount_other": "{{count}} کاربر",
"permissionsCount_other": "{{count}} مجوز",
"stats": {
"totalRoles": "کل نقش‌ها",
"active": "فعال",
"system": "سیستمی"
},
"actions": {
"edit": "ویرایش",
"delete": "حذف"
},
"modal": {
"createTitle": "ایجاد نقش",
"editTitle": "ویرایش نقش",
"close": "بستن"
},
"form": {
"name": "نام نقش",
"namePlaceholder": "مثلاً مدیر محتوا",
"description": "توضیحات",
"descriptionPlaceholder": "کاربرد این نقش...",
"level": "سطح اولویت",
"levelValue": "مقدار سطح",
"levelHint": "سطح بالاتر = اختیارات بیشتر. کاربران فقط می‌توانند نقش‌هایی با سطح پایین‌تر از خود را مدیریت کنند.",
"color": "رنگ",
"presets": "الگوهای مجوز",
"permissions": "مجوزها",
"toggleSection": "تغییر وضعیت تمام مجوزهای {{section}}",
"selectedPermissions_other": "{{count}} مجوز انتخاب شده",
"cancel": "لغو",
"saving": "در حال ذخیره...",
"save": "ذخیره"
},
"presets": {
"moderator": "مدیر محتوا",
"marketer": "بازاریاب",
"support": "پشتیبانی"
},
"confirm": {
"title": "حذف نقش؟",
"text": "این نقش برای همیشه حذف خواهد شد. کاربران دارای این نقش مجوزهای آن را از دست خواهند داد.",
"cancel": "لغو",
"delete": "حذف",
"deleting": "در حال حذف..."
},
"errors": {
"loadFailed": "بارگذاری نقش‌ها ناموفق بود",
"createFailed": "ایجاد نقش ناموفق بود",
"updateFailed": "به‌روزرسانی نقش ناموفق بود",
"nameRequired": "نام نقش الزامی است"
}
},
"roleAssign": {
"title": "تخصیص نقش",
"subtitle": "تخصیص و مدیریت نقش‌های کاربران",
"assignSection": "تخصیص نقش",
"userLabel": "کاربر",
"searchPlaceholder": "جستجو بر اساس نام، نام کاربری، شناسه تلگرام یا ایمیل...",
"clearUser": "پاک کردن کاربر انتخاب‌شده",
"noUsersFound": "کاربری یافت نشد",
"roleLabel": "نقش",
"selectRole": "یک نقش انتخاب کنید...",
"expiresLabel": "تاریخ انقضا (اختیاری)",
"expiresHint": "برای تخصیص دائمی خالی بگذارید",
"assignButton": "تخصیص",
"assigning": "در حال تخصیص...",
"assignSuccess": "نقش با موفقیت تخصیص داده شد",
"currentAssignments": "تخصیص‌های فعلی",
"totalAssignments_other": "{{count}} تخصیص",
"noAssignments": "تخصیص نقشی یافت نشد",
"unknownUser": "کاربر ناشناخته",
"system": "سیستم",
"permanent": "دائمی",
"expired": "منقضی شده",
"revoke": "لغو",
"revokeAriaLabel": "لغو نقش {{role}} از {{user}}",
"table": {
"user": "کاربر",
"role": "نقش",
"assignedBy": "تخصیص‌دهنده",
"assignedAt": "تاریخ تخصیص",
"expires": "انقضا",
"actions": "عملیات"
},
"pagination": {
"showing": "{{from}}-{{to}} از {{total}}",
"prev": "صفحه قبل",
"next": "صفحه بعد"
},
"confirm": {
"title": "لغو نقش؟",
"text": "این کاربر فوراً تمام مجوزهای مرتبط با این نقش را از دست خواهد داد.",
"cancel": "لغو",
"revoke": "لغو نقش",
"revoking": "در حال لغو..."
},
"errors": {
"userRequired": "لطفاً یک کاربر انتخاب کنید",
"roleRequired": "لطفاً یک نقش انتخاب کنید",
"assignFailed": "تخصیص نقش ناموفق بود"
}
},
"policies": {
"title": "سیاست‌های دسترسی",
"subtitle": "مدیریت سیاست‌های کنترل دسترسی ABAC",
"createPolicy": "ایجاد سیاست",
"noPolicies": "سیاستی یافت نشد",
"inactiveBadge": "غیرفعال",
"effectAllow": "اجازه",
"effectDeny": "رد",
"global": "سراسری",
"unknownRole": "نقش ناشناخته",
"roleLabel": "نقش",
"priorityLabel": "اولویت",
"stats": {
"total": "کل سیاست‌ها",
"allow": "اجازه",
"deny": "رد",
"active": "فعال"
},
"actions": {
"edit": "ویرایش",
"delete": "حذف"
},
"modal": {
"createTitle": "ایجاد سیاست",
"editTitle": "ویرایش سیاست",
"close": "بستن"
},
"form": {
"name": "نام سیاست",
"namePlaceholder": "مثلاً مسدودسازی دسترسی شبانه",
"description": "توضیحات",
"descriptionPlaceholder": "عملکرد این سیاست...",
"effect": "اثر",
"resource": "منبع",
"selectResource": "یک منبع انتخاب کنید...",
"actions": "عملیات",
"role": "نقش (اختیاری)",
"globalOption": "سراسری (همه نقش‌ها)",
"roleHint": "سراسری بگذارید تا سیاست برای همه نقش‌ها اعمال شود.",
"priority": "اولویت",
"priorityHint": "سیاست‌های با اولویت بالاتر ابتدا ارزیابی می‌شوند. رد در اولویت مساوی بر اجازه غلبه می‌کند.",
"conditions": "شرایط",
"cancel": "لغو",
"saving": "در حال ذخیره...",
"save": "ذخیره"
},
"conditions": {
"timeRange": "بازه زمانی",
"timeStart": "زمان شروع",
"timeEnd": "زمان پایان",
"ipWhitelist": "لیست سفید IP",
"ipPlaceholder": "IP را وارد کنید و Enter بزنید...",
"removeIp": "حذف {{ip}}",
"ipCount_other": "{{count}} IP",
"rateLimit": "محدودیت نرخ",
"rateLimitValue": "مقدار محدودیت نرخ",
"rateValue": "{{count}}/ساعت",
"perHour": "عملیات در ساعت"
},
"confirm": {
"title": "حذف سیاست؟",
"text": "این سیاست برای همیشه حذف خواهد شد. قوانین کنترل دسترسی مجدداً محاسبه خواهند شد.",
"cancel": "لغو",
"delete": "حذف",
"deleting": "در حال حذف..."
},
"errors": {
"loadFailed": "بارگذاری سیاست‌ها ناموفق بود",
"createFailed": "ایجاد سیاست ناموفق بود",
"updateFailed": "به‌روزرسانی سیاست ناموفق بود",
"nameRequired": "نام سیاست الزامی است",
"resourceRequired": "لطفاً یک منبع انتخاب کنید",
"actionsRequired": "لطفاً حداقل یک عملیات انتخاب کنید"
}
},
"auditLog": {
"title": "گزارش بازرسی",
"subtitle": "بررسی فعالیت سیستم و تاریخچه دسترسی",
"back": "بازگشت",
"exportCsv": "خروجی CSV",
"exporting": "در حال خروجی...",
"refresh": "بازخوانی",
"unknownUser": "کاربر ناشناخته",
"noEntries": "رکوردی در گزارش بازرسی یافت نشد",
"totalEntries_other": "{{count}} رکورد",
"autoRefresh": {
"label": "بازخوانی خودکار",
"tooltip": "بازخوانی خودکار هر ۳۰ ثانیه"
},
"filters": {
"title": "فیلترها",
"active": "فعال",
"action": "عملیات",
"actionPlaceholder": "جستجو بر اساس عملیات...",
"resource": "نوع منبع",
"allResources": "همه منابع",
"status": "وضعیت",
"allStatuses": "همه وضعیت‌ها",
"dateFrom": "از تاریخ",
"dateTo": "تا تاریخ",
"apply": "اعمال",
"clear": "پاک کردن"
},
"status": {
"success": "موفق",
"denied": "رد شده",
"error": "خطا"
},
"resourceTypes": {
"users": "کاربران",
"tickets": "تیکت‌ها",
"roles": "نقش‌ها",
"policies": "سیاست‌ها",
"settings": "تنظیمات",
"broadcasts": "پیام‌رسانی",
"tariffs": "تعرفه‌ها",
"servers": "سرورها",
"payments": "پرداخت‌ها",
"campaigns": "کمپین‌ها",
"promocodes": "کدهای تخفیف"
},
"details": {
"userAgent": "عامل کاربر",
"requestPath": "مسیر درخواست",
"ipAddress": "آدرس IP",
"timestamp": "زمان",
"before": "قبل",
"after": "بعد",
"fullDetails": "جزئیات کامل"
},
"time": {
"justNow": "همین الان",
"minutesAgo_other": "{{count}} دقیقه پیش",
"hoursAgo_other": "{{count}} ساعت پیش",
"daysAgo_other": "{{count}} روز پیش"
},
"pagination": {
"pageSize": "در هر صفحه:",
"pageOf": "{{current}} / {{total}}",
"first": "صفحه اول",
"previous": "صفحه قبل",
"next": "صفحه بعد",
"last": "صفحه آخر"
},
"errors": {
"loadFailed": "بارگذاری گزارش بازرسی ناموفق بود",
"retry": "تلاش مجدد"
}
}
},
"blocking": {

View File

@@ -884,7 +884,11 @@
"pinnedMessages": "Закреплённые",
"partners": "Партнёры",
"withdrawals": "Выводы",
"channelSubscriptions": "Обязательные каналы"
"channelSubscriptions": "Обязательные каналы",
"roles": "Роли",
"roleAssign": "Назначение ролей",
"policies": "Политики доступа",
"auditLog": "Журнал аудита"
},
"panel": {
"title": "Панель администратора",
@@ -912,7 +916,11 @@
"pinnedMessagesDesc": "Управление закреплёнными сообщениями",
"partnersDesc": "Управление заявками партнёров и комиссиями",
"withdrawalsDesc": "Проверка и обработка заявок на вывод",
"channelSubscriptionsDesc": "Управление обязательными подписками на каналы"
"channelSubscriptionsDesc": "Управление обязательными подписками на каналы",
"rolesDesc": "Управление ролями и правами администраторов",
"roleAssignDesc": "Назначение и отзыв ролей пользователей",
"policiesDesc": "Настройка политик контроля доступа ABAC",
"auditLogDesc": "Просмотр активности системы и истории доступа"
},
"trafficUsage": {
"title": "Расход трафика",
@@ -3063,7 +3071,8 @@
"marketing": "Маркетинг",
"system": "Система",
"tariffs": "Тарифы и продажи",
"users": "Пользователи"
"users": "Пользователи",
"security": "Безопасность"
},
"theme": {
"accentColor": "Акцентный цвет",
@@ -3472,6 +3481,283 @@
"unhealthy": "Проблема",
"components": "Компоненты",
"uptime": "Аптайм"
},
"roles": {
"title": "Роли и права",
"subtitle": "Управление ролями администраторов и их правами",
"createRole": "Создать роль",
"noRoles": "Роли не найдены",
"systemBadge": "Системная",
"inactiveBadge": "Неактивна",
"levelLabel": "Уровень",
"usersCount_one": "{{count}} пользователь",
"usersCount_few": "{{count}} пользователя",
"usersCount_many": "{{count}} пользователей",
"permissionsCount_one": "{{count}} разрешение",
"permissionsCount_few": "{{count}} разрешения",
"permissionsCount_many": "{{count}} разрешений",
"stats": {
"totalRoles": "Всего ролей",
"active": "Активные",
"system": "Системные"
},
"actions": {
"edit": "Редактировать",
"delete": "Удалить"
},
"modal": {
"createTitle": "Создание роли",
"editTitle": "Редактирование роли",
"close": "Закрыть"
},
"form": {
"name": "Название роли",
"namePlaceholder": "например, Модератор",
"description": "Описание",
"descriptionPlaceholder": "Для чего нужна эта роль...",
"level": "Уровень приоритета",
"levelValue": "Значение уровня",
"levelHint": "Чем выше уровень, тем больше полномочий. Пользователи могут управлять только ролями с уровнем ниже своего.",
"color": "Цвет",
"presets": "Шаблоны прав",
"permissions": "Разрешения",
"toggleSection": "Переключить все права {{section}}",
"selectedPermissions_one": "{{count}} разрешение выбрано",
"selectedPermissions_few": "{{count}} разрешения выбрано",
"selectedPermissions_many": "{{count}} разрешений выбрано",
"cancel": "Отмена",
"saving": "Сохранение...",
"save": "Сохранить"
},
"presets": {
"moderator": "Модератор",
"marketer": "Маркетолог",
"support": "Поддержка"
},
"confirm": {
"title": "Удалить роль?",
"text": "Роль будет безвозвратно удалена. Пользователи с этой ролью потеряют её права.",
"cancel": "Отмена",
"delete": "Удалить",
"deleting": "Удаление..."
},
"errors": {
"loadFailed": "Не удалось загрузить роли",
"createFailed": "Не удалось создать роль",
"updateFailed": "Не удалось обновить роль",
"nameRequired": "Укажите название роли"
}
},
"roleAssign": {
"title": "Назначение ролей",
"subtitle": "Назначение и управление ролями пользователей",
"assignSection": "Назначить роль",
"userLabel": "Пользователь",
"searchPlaceholder": "Поиск по имени, username, Telegram ID или email...",
"clearUser": "Очистить выбранного пользователя",
"noUsersFound": "Пользователи не найдены",
"roleLabel": "Роль",
"selectRole": "Выберите роль...",
"expiresLabel": "Истекает (необязательно)",
"expiresHint": "Оставьте пустым для бессрочного назначения",
"assignButton": "Назначить",
"assigning": "Назначение...",
"assignSuccess": "Роль успешно назначена",
"currentAssignments": "Текущие назначения",
"totalAssignments_one": "{{count}} назначение",
"totalAssignments_few": "{{count}} назначения",
"totalAssignments_many": "{{count}} назначений",
"noAssignments": "Назначения ролей не найдены",
"unknownUser": "Неизвестный пользователь",
"system": "Система",
"permanent": "Бессрочно",
"expired": "истекло",
"revoke": "Отозвать",
"revokeAriaLabel": "Отозвать роль {{role}} у {{user}}",
"table": {
"user": "Пользователь",
"role": "Роль",
"assignedBy": "Назначил",
"assignedAt": "Дата назначения",
"expires": "Истекает",
"actions": "Действия"
},
"pagination": {
"showing": "{{from}}-{{to}} из {{total}}",
"prev": "Предыдущая страница",
"next": "Следующая страница"
},
"confirm": {
"title": "Отозвать роль?",
"text": "Пользователь немедленно потеряет все права, связанные с этой ролью.",
"cancel": "Отмена",
"revoke": "Отозвать",
"revoking": "Отзыв..."
},
"errors": {
"userRequired": "Выберите пользователя",
"roleRequired": "Выберите роль",
"assignFailed": "Не удалось назначить роль"
}
},
"policies": {
"title": "Политики доступа",
"subtitle": "Управление политиками контроля доступа ABAC",
"createPolicy": "Создать политику",
"noPolicies": "Политики не найдены",
"inactiveBadge": "Неактивна",
"effectAllow": "Разрешить",
"effectDeny": "Запретить",
"global": "Глобальная",
"unknownRole": "Неизвестная роль",
"roleLabel": "Роль",
"priorityLabel": "Приоритет",
"stats": {
"total": "Всего политик",
"allow": "Разрешающие",
"deny": "Запрещающие",
"active": "Активные"
},
"actions": {
"edit": "Редактировать",
"delete": "Удалить"
},
"modal": {
"createTitle": "Создание политики",
"editTitle": "Редактирование политики",
"close": "Закрыть"
},
"form": {
"name": "Название политики",
"namePlaceholder": "например, Блокировка ночного доступа",
"description": "Описание",
"descriptionPlaceholder": "Что делает эта политика...",
"effect": "Эффект",
"resource": "Ресурс",
"selectResource": "Выберите ресурс...",
"actions": "Действия",
"role": "Роль (необязательно)",
"globalOption": "Глобальная (все роли)",
"roleHint": "Оставьте Глобальная, чтобы политика применялась ко всем ролям.",
"priority": "Приоритет",
"priorityHint": "Политики с более высоким приоритетом проверяются первыми. Запрет перекрывает Разрешение при равном приоритете.",
"conditions": "Условия",
"cancel": "Отмена",
"saving": "Сохранение...",
"save": "Сохранить"
},
"conditions": {
"timeRange": "Временной диапазон",
"timeStart": "Время начала",
"timeEnd": "Время окончания",
"ipWhitelist": "Белый список IP",
"ipPlaceholder": "Введите IP и нажмите Enter...",
"removeIp": "Удалить {{ip}}",
"ipCount_one": "{{count}} IP",
"ipCount_few": "{{count}} IP",
"ipCount_many": "{{count}} IP",
"rateLimit": "Лимит запросов",
"rateLimitValue": "Значение лимита запросов",
"rateValue": "{{count}}/ч",
"perHour": "действий в час"
},
"confirm": {
"title": "Удалить политику?",
"text": "Политика будет безвозвратно удалена. Правила контроля доступа будут пересчитаны.",
"cancel": "Отмена",
"delete": "Удалить",
"deleting": "Удаление..."
},
"errors": {
"loadFailed": "Не удалось загрузить политики",
"createFailed": "Не удалось создать политику",
"updateFailed": "Не удалось обновить политику",
"nameRequired": "Укажите название политики",
"resourceRequired": "Выберите ресурс",
"actionsRequired": "Выберите хотя бы одно действие"
}
},
"auditLog": {
"title": "Журнал аудита",
"subtitle": "Просмотр активности системы и истории доступа",
"back": "Назад",
"exportCsv": "Экспорт CSV",
"exporting": "Экспорт...",
"refresh": "Обновить",
"unknownUser": "Неизвестный пользователь",
"noEntries": "Записи журнала аудита не найдены",
"totalEntries_one": "{{count}} запись",
"totalEntries_few": "{{count}} записи",
"totalEntries_many": "{{count}} записей",
"autoRefresh": {
"label": "Автообновление",
"tooltip": "Автообновление каждые 30 секунд"
},
"filters": {
"title": "Фильтры",
"active": "Активны",
"action": "Действие",
"actionPlaceholder": "Поиск по действию...",
"resource": "Тип ресурса",
"allResources": "Все ресурсы",
"status": "Статус",
"allStatuses": "Все статусы",
"dateFrom": "Дата от",
"dateTo": "Дата до",
"apply": "Применить",
"clear": "Сбросить"
},
"status": {
"success": "Успешно",
"denied": "Отказано",
"error": "Ошибка"
},
"resourceTypes": {
"users": "Пользователи",
"tickets": "Тикеты",
"roles": "Роли",
"policies": "Политики",
"settings": "Настройки",
"broadcasts": "Рассылки",
"tariffs": "Тарифы",
"servers": "Серверы",
"payments": "Платежи",
"campaigns": "Кампании",
"promocodes": "Промокоды"
},
"details": {
"userAgent": "User Agent",
"requestPath": "Путь запроса",
"ipAddress": "IP-адрес",
"timestamp": "Время",
"before": "До",
"after": "После",
"fullDetails": "Полные данные"
},
"time": {
"justNow": "Только что",
"minutesAgo_one": "{{count}} мин назад",
"minutesAgo_few": "{{count}} мин назад",
"minutesAgo_many": "{{count}} мин назад",
"hoursAgo_one": "{{count}} ч назад",
"hoursAgo_few": "{{count}} ч назад",
"hoursAgo_many": "{{count}} ч назад",
"daysAgo_one": "{{count}} день назад",
"daysAgo_few": "{{count}} дня назад",
"daysAgo_many": "{{count}} дней назад"
},
"pagination": {
"pageSize": "На странице:",
"pageOf": "{{current}} / {{total}}",
"first": "Первая страница",
"previous": "Предыдущая страница",
"next": "Следующая страница",
"last": "Последняя страница"
},
"errors": {
"loadFailed": "Не удалось загрузить журнал аудита",
"retry": "Попробовать снова"
}
}
},
"profile": {

View File

@@ -742,7 +742,11 @@
"pinnedMessages": "置顶消息",
"partners": "合作伙伴",
"withdrawals": "提现",
"channelSubscriptions": "必订频道"
"channelSubscriptions": "必订频道",
"roles": "角色",
"roleAssign": "角色分配",
"policies": "访问策略",
"auditLog": "审计日志"
},
"panel": {
"title": "管理面板",
@@ -770,7 +774,11 @@
"pinnedMessagesDesc": "管理用户置顶消息",
"partnersDesc": "管理合作伙伴申请和佣金",
"withdrawalsDesc": "审核和处理提现请求",
"channelSubscriptionsDesc": "管理必订频道订阅"
"channelSubscriptionsDesc": "管理必订频道订阅",
"rolesDesc": "管理管理员角色和权限",
"roleAssignDesc": "分配和撤销用户角色",
"policiesDesc": "配置ABAC访问控制策略",
"auditLogDesc": "查看系统活动和访问历史"
},
"trafficUsage": {
"title": "流量使用",
@@ -2201,7 +2209,8 @@
"marketing": "营销",
"system": "系统",
"tariffs": "套餐与销售",
"users": "用户"
"users": "用户",
"security": "安全"
},
"theme": {
"accentColor": "强调色",
@@ -2809,6 +2818,265 @@
"node": "节点",
"requests": "请求数",
"ipHistory": "IP历史"
},
"roles": {
"title": "角色与权限",
"subtitle": "管理管理员角色及其权限",
"createRole": "创建角色",
"noRoles": "未找到角色",
"systemBadge": "系统",
"inactiveBadge": "未激活",
"levelLabel": "级别",
"usersCount_other": "{{count}} 个用户",
"permissionsCount_other": "{{count}} 个权限",
"stats": {
"totalRoles": "角色总数",
"active": "活跃",
"system": "系统"
},
"actions": {
"edit": "编辑",
"delete": "删除"
},
"modal": {
"createTitle": "创建角色",
"editTitle": "编辑角色",
"close": "关闭"
},
"form": {
"name": "角色名称",
"namePlaceholder": "例如:版主",
"description": "描述",
"descriptionPlaceholder": "此角色的用途...",
"level": "优先级",
"levelValue": "级别值",
"levelHint": "级别越高,权限越大。用户只能管理级别低于自己的角色。",
"color": "颜色",
"presets": "权限预设",
"permissions": "权限",
"toggleSection": "切换所有 {{section}} 权限",
"selectedPermissions_other": "已选择 {{count}} 个权限",
"cancel": "取消",
"saving": "保存中...",
"save": "保存"
},
"presets": {
"moderator": "版主",
"marketer": "营销员",
"support": "客服"
},
"confirm": {
"title": "删除角色?",
"text": "此角色将被永久删除。拥有此角色的用户将失去其权限。",
"cancel": "取消",
"delete": "删除",
"deleting": "删除中..."
},
"errors": {
"loadFailed": "加载角色失败",
"createFailed": "创建角色失败",
"updateFailed": "更新角色失败",
"nameRequired": "请输入角色名称"
}
},
"roleAssign": {
"title": "角色分配",
"subtitle": "分配和管理用户角色",
"assignSection": "分配角色",
"userLabel": "用户",
"searchPlaceholder": "按名称、用户名、Telegram ID或邮箱搜索...",
"clearUser": "清除已选用户",
"noUsersFound": "未找到用户",
"roleLabel": "角色",
"selectRole": "选择角色...",
"expiresLabel": "到期时间(可选)",
"expiresHint": "留空表示永久分配",
"assignButton": "分配",
"assigning": "分配中...",
"assignSuccess": "角色分配成功",
"currentAssignments": "当前分配",
"totalAssignments_other": "共 {{count}} 个分配",
"noAssignments": "未找到角色分配",
"unknownUser": "未知用户",
"system": "系统",
"permanent": "永久",
"expired": "已过期",
"revoke": "撤销",
"revokeAriaLabel": "撤销 {{user}} 的角色 {{role}}",
"table": {
"user": "用户",
"role": "角色",
"assignedBy": "分配者",
"assignedAt": "分配时间",
"expires": "到期",
"actions": "操作"
},
"pagination": {
"showing": "{{from}}-{{to}} / {{total}}",
"prev": "上一页",
"next": "下一页"
},
"confirm": {
"title": "撤销角色?",
"text": "该用户将立即失去与此角色相关的所有权限。",
"cancel": "取消",
"revoke": "撤销",
"revoking": "撤销中..."
},
"errors": {
"userRequired": "请选择用户",
"roleRequired": "请选择角色",
"assignFailed": "角色分配失败"
}
},
"policies": {
"title": "访问策略",
"subtitle": "管理ABAC访问控制策略",
"createPolicy": "创建策略",
"noPolicies": "未找到策略",
"inactiveBadge": "未激活",
"effectAllow": "允许",
"effectDeny": "拒绝",
"global": "全局",
"unknownRole": "未知角色",
"roleLabel": "角色",
"priorityLabel": "优先级",
"stats": {
"total": "策略总数",
"allow": "允许",
"deny": "拒绝",
"active": "活跃"
},
"actions": {
"edit": "编辑",
"delete": "删除"
},
"modal": {
"createTitle": "创建策略",
"editTitle": "编辑策略",
"close": "关闭"
},
"form": {
"name": "策略名称",
"namePlaceholder": "例如:阻止夜间访问",
"description": "描述",
"descriptionPlaceholder": "此策略的作用...",
"effect": "效果",
"resource": "资源",
"selectResource": "选择资源...",
"actions": "操作",
"role": "角色(可选)",
"globalOption": "全局(所有角色)",
"roleHint": "保留全局以将策略应用于所有角色。",
"priority": "优先级",
"priorityHint": "优先级高的策略先被评估。同等优先级下,拒绝覆盖允许。",
"conditions": "条件",
"cancel": "取消",
"saving": "保存中...",
"save": "保存"
},
"conditions": {
"timeRange": "时间范围",
"timeStart": "开始时间",
"timeEnd": "结束时间",
"ipWhitelist": "IP白名单",
"ipPlaceholder": "输入IP并按回车...",
"removeIp": "移除 {{ip}}",
"ipCount_other": "{{count}} 个IP",
"rateLimit": "速率限制",
"rateLimitValue": "速率限制值",
"rateValue": "{{count}}/小时",
"perHour": "每小时操作数"
},
"confirm": {
"title": "删除策略?",
"text": "此策略将被永久删除。访问控制规则将被重新计算。",
"cancel": "取消",
"delete": "删除",
"deleting": "删除中..."
},
"errors": {
"loadFailed": "加载策略失败",
"createFailed": "创建策略失败",
"updateFailed": "更新策略失败",
"nameRequired": "请输入策略名称",
"resourceRequired": "请选择资源",
"actionsRequired": "请至少选择一个操作"
}
},
"auditLog": {
"title": "审计日志",
"subtitle": "查看系统活动和访问历史",
"back": "返回",
"exportCsv": "导出CSV",
"exporting": "导出中...",
"refresh": "刷新",
"unknownUser": "未知用户",
"noEntries": "未找到审计日志条目",
"totalEntries_other": "{{count}} 条记录",
"autoRefresh": {
"label": "自动刷新",
"tooltip": "每30秒自动刷新"
},
"filters": {
"title": "筛选",
"active": "已激活",
"action": "操作",
"actionPlaceholder": "按操作搜索...",
"resource": "资源类型",
"allResources": "所有资源",
"status": "状态",
"allStatuses": "所有状态",
"dateFrom": "开始日期",
"dateTo": "结束日期",
"apply": "应用",
"clear": "清除"
},
"status": {
"success": "成功",
"denied": "拒绝",
"error": "错误"
},
"resourceTypes": {
"users": "用户",
"tickets": "工单",
"roles": "角色",
"policies": "策略",
"settings": "设置",
"broadcasts": "群发",
"tariffs": "套餐",
"servers": "服务器",
"payments": "支付",
"campaigns": "活动",
"promocodes": "促销码"
},
"details": {
"userAgent": "用户代理",
"requestPath": "请求路径",
"ipAddress": "IP地址",
"timestamp": "时间戳",
"before": "之前",
"after": "之后",
"fullDetails": "完整详情"
},
"time": {
"justNow": "刚刚",
"minutesAgo_other": "{{count}} 分钟前",
"hoursAgo_other": "{{count}} 小时前",
"daysAgo_other": "{{count}} 天前"
},
"pagination": {
"pageSize": "每页:",
"pageOf": "{{current}} / {{total}}",
"first": "第一页",
"previous": "上一页",
"next": "下一页",
"last": "最后一页"
},
"errors": {
"loadFailed": "加载审计日志失败",
"retry": "重试"
}
}
}
}