From c3cf8058278464c2390f38c1fb8be72036f2edd4 Mon Sep 17 00:00:00 2001 From: Fringg Date: Sat, 7 Mar 2026 06:23:39 +0300 Subject: [PATCH] refactor: load RBAC users from API for audit log user filter Instead of extracting users from log entries, fetch all users with RBAC roles via dedicated endpoint for complete user list. --- src/api/rbac.ts | 17 ++++++++++++++ src/pages/AdminAuditLog.tsx | 47 ++++++++++++------------------------- 2 files changed, 32 insertions(+), 32 deletions(-) diff --git a/src/api/rbac.ts b/src/api/rbac.ts index a0af13b..39cbd45 100644 --- a/src/api/rbac.ts +++ b/src/api/rbac.ts @@ -49,6 +49,16 @@ export interface UserRoleAssignment { user_telegram_id: number | null; } +export interface AdminWithRoles { + user_id: number; + telegram_id: number | null; + username: string | null; + first_name: string | null; + last_name: string | null; + email: string | null; + role_names: string[]; +} + export interface AssignRolePayload { user_id: number; role_id: number; @@ -167,6 +177,13 @@ export const rbacApi = { return response.data; }, + // --- RBAC Users --- + + getRbacUsers: async (): Promise => { + const response = await apiClient.get(`${BASE}/users`); + return response.data; + }, + // --- Role Users --- getRoleUsers: async (roleId: number): Promise => { diff --git a/src/pages/AdminAuditLog.tsx b/src/pages/AdminAuditLog.tsx index a4dc8f3..96fec9b 100644 --- a/src/pages/AdminAuditLog.tsx +++ b/src/pages/AdminAuditLog.tsx @@ -1,4 +1,4 @@ -import { useState, useCallback, useMemo, useEffect } from 'react'; +import { useState, useCallback, useMemo } from 'react'; import { useNavigate } from 'react-router'; import { useQuery } from '@tanstack/react-query'; import { useTranslation } from 'react-i18next'; @@ -415,11 +415,6 @@ function LogEntryCard({ entry, isExpanded, onToggle }: LogEntryCardProps) { // === Main Page === -interface KnownUser { - name: string; - email: string | null; -} - export default function AdminAuditLog() { const { t } = useTranslation(); const navigate = useNavigate(); @@ -440,9 +435,6 @@ export default function AdminAuditLog() { const [exporting, setExporting] = useState(false); const [exportError, setExportError] = useState(null); - // Known users accumulated from audit log entries - const [knownUsers, setKnownUsers] = useState>(new Map()); - // Build query params const queryParams = useMemo((): AuditLogFilters => { const params: AuditLogFilters = { @@ -480,23 +472,12 @@ export default function AdminAuditLog() { refetchInterval: autoRefresh ? AUTO_REFRESH_INTERVAL : false, }); - // Accumulate unique users from audit log entries - useEffect(() => { - if (!data?.items?.length) return; - setKnownUsers((prev) => { - const next = new Map(prev); - let changed = false; - for (const entry of data.items) { - const name = entry.user_first_name || entry.user_email || `#${entry.user_id}`; - const existing = next.get(entry.user_id); - if (!existing || existing.name !== name || existing.email !== entry.user_email) { - next.set(entry.user_id, { name, email: entry.user_email }); - changed = true; - } - } - return changed ? next : prev; - }); - }, [data?.items]); + // RBAC users for filter chips + const { data: rbacUsers } = useQuery({ + queryKey: ['rbac-users'], + queryFn: () => rbacApi.getRbacUsers(), + staleTime: 5 * 60 * 1000, + }); const entries = data?.items ?? []; const total = data?.total ?? 0; @@ -669,23 +650,25 @@ export default function AdminAuditLog() {
{/* User filter */} - {knownUsers.size > 0 && ( + {rbacUsers && rbacUsers.length > 0 && (
- {Array.from(knownUsers.entries()).map(([uid, user]) => { - const isSelected = filters.userId === String(uid); + {rbacUsers.map((ru) => { + const isSelected = filters.userId === String(ru.user_id); + const displayName = + ru.first_name || ru.email || ru.username || `#${ru.user_id}`; return ( ); })}