diff --git a/src/locales/en.json b/src/locales/en.json index f4a8923..3104367 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -2844,6 +2844,7 @@ "timestamp": "Timestamp", "before": "Before", "after": "After", + "requestBody": "Request Body", "fullDetails": "Full Details" }, "time": { diff --git a/src/locales/fa.json b/src/locales/fa.json index 8b875d8..65cecef 100644 --- a/src/locales/fa.json +++ b/src/locales/fa.json @@ -2629,6 +2629,7 @@ "timestamp": "زمان", "before": "قبل", "after": "بعد", + "requestBody": "داده‌های درخواست", "fullDetails": "جزئیات کامل" }, "time": { diff --git a/src/locales/ru.json b/src/locales/ru.json index 6e37bd5..3ccbb0c 100644 --- a/src/locales/ru.json +++ b/src/locales/ru.json @@ -3396,6 +3396,7 @@ "timestamp": "Время", "before": "До", "after": "После", + "requestBody": "Данные запроса", "fullDetails": "Полные данные" }, "time": { diff --git a/src/locales/zh.json b/src/locales/zh.json index b5fccc6..808c61a 100644 --- a/src/locales/zh.json +++ b/src/locales/zh.json @@ -2628,6 +2628,7 @@ "timestamp": "时间戳", "before": "之前", "after": "之后", + "requestBody": "请求数据", "fullDetails": "完整详情" }, "time": { diff --git a/src/pages/AdminAuditLog.tsx b/src/pages/AdminAuditLog.tsx index 53a7235..8ffbc0e 100644 --- a/src/pages/AdminAuditLog.tsx +++ b/src/pages/AdminAuditLog.tsx @@ -83,15 +83,30 @@ const SearchIcon = () => ( const RESOURCE_TYPES = [ 'users', 'tickets', - 'roles', - 'policies', - 'settings', + 'stats', 'broadcasts', 'tariffs', - 'servers', - 'payments', - 'campaigns', 'promocodes', + 'promo_groups', + 'promo_offers', + 'campaigns', + 'partners', + 'withdrawals', + 'payments', + 'payment_methods', + 'servers', + 'remnawave', + 'traffic', + 'settings', + 'roles', + 'audit_log', + 'channels', + 'ban_system', + 'wheel', + 'apps', + 'email_templates', + 'pinned_messages', + 'updates', ] as const; const STATUS_OPTIONS = ['success', 'denied', 'error'] as const; @@ -118,6 +133,24 @@ const INITIAL_FILTERS: FiltersState = { // === Utility functions === +function translateAction( + action: string, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + t: any, +): string { + return action + .split(',') + .map((perm: string) => { + const trimmed = perm.trim(); + const [section, act] = trimmed.split(':', 2); + if (!section || !act) return trimmed; + const sectionLabel = t(`admin.roles.form.permissionSections.${section}`, section) as string; + const actionLabel = t(`admin.roles.form.permissionActions.${act}`, act) as string; + return `${sectionLabel}: ${actionLabel}`; + }) + .join(', '); +} + function formatRelativeTime( dateString: string, t: (key: string, opts?: Record) => string, @@ -228,12 +261,18 @@ function LogEntryCard({ entry, isExpanded, onToggle }: LogEntryCardProps) { status={status} label={t(`admin.auditLog.status.${status}`, { defaultValue: status })} /> - {entry.action} + + {translateAction(entry.action, t)} + {/* Resource */}
- {entry.resource_type} + + {entry.resource_type + ? t(`admin.roles.form.permissionSections.${entry.resource_type}`, entry.resource_type) + : null} + {entry.resource_id && ( #{entry.resource_id} @@ -323,6 +362,20 @@ function LogEntryCard({ entry, isExpanded, onToggle }: LogEntryCardProps) {
)} + + {/* Request body */} + {entry.details && + 'request_body' in entry.details && + entry.details.request_body != null && ( +
+

+ {t('admin.auditLog.details.requestBody')} +

+
+                    {JSON.stringify(entry.details.request_body, null, 2)}
+                  
+
+ )} {/* Full details JSON */} @@ -622,7 +675,7 @@ export default function AdminAuditLog() { {RESOURCE_TYPES.map((type) => ( ))}