Skip to content

Conversation

@rootflo-hardik
Copy link
Contributor

@rootflo-hardik rootflo-hardik commented Jan 5, 2026

Summary by CodeRabbit

  • New Features
    • Added user management system with a dedicated page accessible via a new button in the top navigation.
    • Enabled creating, viewing, editing, and deleting user accounts.
    • Implemented client-side search and filtering for users.
    • Added permission-based controls for user management actions.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Jan 5, 2026

Caution

Review failed

The pull request is closed.

📝 Walkthrough

Walkthrough

This PR introduces a complete user management system to the Wavefront application. It adds CRUD API endpoints to UserService, implements React Query hooks for data fetching and mutations with validation schemas, and provides a full-featured UI page with user table, create/edit dialogs, and delete confirmation flow. The system integrates with existing notification and permission infrastructure.

Changes

Cohort / File(s) Summary
API Service Layer
wavefront/client/src/api/user-service.ts
Added 4 new CRUD methods: listUsers(), createUser(), updateUser(), and deleteUser() with corresponding HTTP endpoints and response shapes.
React Query Infrastructure
wavefront/client/src/hooks/data/query-keys.ts, wavefront/client/src/hooks/data/query-functions.ts, wavefront/client/src/hooks/data/fetch-hooks.ts
Added query key builders (getUsersKey(), getUserKey()), query function (getUsersQueryFn()), and fetch hook (useGetUsers()) for user list retrieval and caching.
React Query Mutations
wavefront/client/src/hooks/data/mutation-functions.ts, wavefront/client/src/hooks/data/mutation-hooks.ts
Added mutation functions and custom hooks (useCreateUser(), useUpdateUser(), useDeleteUser()) with error handling, notifications, and cache invalidation.
Validation & Types
wavefront/client/src/types/user.ts
Added zod schemas (createUserSchema, updateUserSchema) with corresponding TypeScript types for form validation.
User Management UI Components
wavefront/client/src/pages/apps/users/index.tsx, wavefront/client/src/pages/apps/users/CreateUserDialog.tsx, wavefront/client/src/pages/apps/users/EditUserDialog.tsx
New page component with searchable users table, permission-gated edit/delete actions, and modal dialogs for create/edit flows with form validation and confirmation.
Navigation & Routing
wavefront/client/src/components/topbar/Topbar.tsx, wavefront/client/src/router/routes.tsx
Added User Management button to top bar with Settings icon and new /apps/users private route.
Backend Service
wavefront/server/apps/floconsole/floconsole/services/user_service.py
Added refresh=True parameter to delete_user method for object refresh after update.
Cleanup
wavefront/client/src/pages/apps/layout.tsx
Removed unused PermissionIcon import.

Sequence Diagram(s)

sequenceDiagram
    participant User as User
    participant UI as UsersPage UI
    participant Dialog as CreateUserDialog
    participant MutationHook as useCreateUser Hook
    participant API as UserService API
    participant Backend as Backend API
    participant QueryCache as React Query Cache

    User->>UI: Clicks "Create User"
    UI->>Dialog: Opens with isOpen=true
    User->>Dialog: Fills form & submits
    Dialog->>MutationHook: Calls mutate(userData)
    MutationHook->>API: userService.createUser(data)
    API->>Backend: POST /v1/users
    Backend-->>API: { user: IUser }
    MutationHook->>UI: Shows success notification
    MutationHook->>QueryCache: Invalidate getUsersKey()
    QueryCache-->>UI: Refetch users list
    MutationHook->>Dialog: Calls onSuccess callback
    Dialog->>UI: Closes dialog
Loading
sequenceDiagram
    participant User as User
    participant UI as UsersPage UI
    participant ConfirmDialog as Delete Confirmation
    participant MutationHook as useDeleteUser Hook
    participant API as UserService API
    participant Backend as Backend API
    participant QueryCache as React Query Cache

    User->>UI: Clicks delete icon on user row
    UI->>ConfirmDialog: Opens confirmation dialog
    User->>ConfirmDialog: Confirms deletion
    ConfirmDialog->>MutationHook: Calls mutate(userId)
    MutationHook->>API: userService.deleteUser(userId)
    API->>Backend: DELETE /v1/users/{userId}
    Backend-->>API: { message: string }
    MutationHook->>UI: Shows success notification
    MutationHook->>QueryCache: Invalidate getUsersKey()
    QueryCache-->>UI: Refetch users list
    ConfirmDialog->>UI: Closes dialog
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • vizsatiz

Poem

🐰 Hops through the user management land,
CRUD operations now at hand,
Dialogs dance, mutations play,
Query cache keeps it fresh all day,
Create, update, delete with care—
User management, everywhere!

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main changes: comprehensive frontend user management features including CRUD operations, hooks, dialogs, and a users page.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

📜 Recent review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6463224 and 2f6bbf7.

📒 Files selected for processing (9)
  • wavefront/client/src/components/topbar/Topbar.tsx
  • wavefront/client/src/hooks/data/fetch-hooks.ts
  • wavefront/client/src/hooks/data/mutation-hooks.ts
  • wavefront/client/src/hooks/data/query-keys.ts
  • wavefront/client/src/pages/apps/layout.tsx
  • wavefront/client/src/pages/apps/users/CreateUserDialog.tsx
  • wavefront/client/src/pages/apps/users/EditUserDialog.tsx
  • wavefront/client/src/pages/apps/users/index.tsx
  • wavefront/client/src/router/routes.tsx

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

Fix all issues with AI Agents 🤖
In @wavefront/client/src/api/user-service.ts:
- Around line 27-54: Add a runtime guard in user-service.ts to ensure the HTTP
client uses HTTPS in production: detect the runtime environment (e.g., NODE_ENV
=== "production") and validate the axios/baseURL used by this.http before
sending sensitive requests from createUser and updateUser; if the baseURL is not
HTTPS, throw or reject with a clear error (or fail-fast during service
initialization) so passwords are never sent over plain HTTP in production.
Ensure the check references the existing this.http or its configured baseURL and
runs at service construction or at the start of createUser/updateUser to prevent
accidental insecure transmissions.

In @wavefront/client/src/hooks/data/fetch-hooks.ts:
- Around line 414-416: The cache key includes appId via getUsersKey(appId || '')
but getUsersQueryFn ignores it and calls
floConsoleService.userService.listUsers(), causing cache inconsistency; either
remove appId from the key if users are global, or update
useGetUsers/getUsersQueryFn to pass the appId into the query function (use
getUsersKey to extract it) and call the app-scoped API (e.g.,
floConsoleService.userService.listUsersForApp or /v1/apps/{appId}/users) so the
request matches the cache scope; update the useQueryInit invocation and the
getUsersQueryFn signature accordingly.

In @wavefront/client/src/pages/apps/[appId]/users/CreateUserDialog.tsx:
- Around line 40-44: Remove the `form` object from the useEffect dependency
array so the effect only runs when `isOpen` changes; update the useEffect
wrapping the `form.reset()` call in CreateUserDialog to depend solely on
`isOpen` (or, alternatively, call `form.reset` via a stable callback provided by
react-hook-form v7+ so no changing `form` reference is required).

In @wavefront/client/src/pages/apps/[appId]/users/index.tsx:
- Around line 34-40: The backend lacks authorization on create_user (POST
/users) and list_users (GET /users) and whoami doesn't return role info; update
the create_user and list_users handlers to require super-admin privileges (add
or call existing auth middleware/guard that checks is_super_admin on the request
user) and ensure they return 403 for unauthorized callers, modify the whoami
handler to include role/super_admin flags in its response, update the frontend
IUser interface to include role/superAdmin (or equivalent) fields, and replace
the hardcoded isSuperAdmin useMemo in users/index.tsx with a real check against
currentUser.role/currentUser.superAdmin from whoami; ensure both frontend UI
controls and backend endpoints consistently enforce the same super-admin rule.

In @wavefront/client/src/types/user.ts:
- Around line 21-41: The updateUserSchema currently permits empty strings and
the controller only filters None, so empty strings get written and even hashed;
update the controller (the handler that currently uses "if v is not None") to
also treat empty strings as omitted (e.g., skip keys where value === ''), ensure
the service code that calls find_one_and_update does not receive '' values, and
add a guard in the password-hashing logic (the service password hashing path) to
only hash/update when password is non-empty and meets length/validation (min 8)
before passing to find_one_and_update.
🧹 Nitpick comments (3)
wavefront/client/src/types/user.ts (1)

1-9: Unconventional import placement.

The import statements (lines 8-9) appear after the IUser interface definition. By convention, all imports should be placed at the top of the file before any other code.

🔎 Suggested fix
+import { emailRegex, passwordRegex } from '@app/utils/regex';
+import { z } from 'zod';
+
 export interface IUser {
   id: string;
   email: string;
   first_name: string;
   last_name: string;
 }
-
-import { emailRegex, passwordRegex } from '@app/utils/regex';
-import { z } from 'zod';
wavefront/client/src/hooks/data/query-functions.ts (1)

16-16: Consider consolidating duplicate IUser type definitions.

The IUser interface appears to be defined in both wavefront/client/src/types/user.ts and wavefront/client/src/pages/types.ts. This code duplication could lead to inconsistencies if one definition is updated without the other.

📋 Recommendation

Keep the type definition only in wavefront/client/src/types/user.ts and update wavefront/client/src/pages/types.ts to import it from there. This ensures a single source of truth for the IUser type.

wavefront/client/src/pages/apps/[appId]/users/index.tsx (1)

100-107: Consider server-side search for better scalability.

The current client-side filtering works well for small-to-medium user lists. For applications with hundreds or thousands of users, consider adding server-side search capabilities to the listUsers endpoint with query parameters.

Example enhancement to the API service:

async listUsers(searchQuery?: string): Promise<IApiResponse<{ users: IUser[] }>> {
  return this.http.get('/v1/users', {
    params: searchQuery ? { search: searchQuery } : undefined
  });
}
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between da52a53 and 6463224.

📒 Files selected for processing (13)
  • wavefront/client/src/api/user-service.ts
  • wavefront/client/src/hooks/data/fetch-hooks.ts
  • wavefront/client/src/hooks/data/mutation-functions.ts
  • wavefront/client/src/hooks/data/mutation-hooks.ts
  • wavefront/client/src/hooks/data/query-functions.ts
  • wavefront/client/src/hooks/data/query-keys.ts
  • wavefront/client/src/pages/apps/[appId]/users/CreateUserDialog.tsx
  • wavefront/client/src/pages/apps/[appId]/users/EditUserDialog.tsx
  • wavefront/client/src/pages/apps/[appId]/users/index.tsx
  • wavefront/client/src/pages/apps/layout.tsx
  • wavefront/client/src/router/routes.tsx
  • wavefront/client/src/types/user.ts
  • wavefront/server/apps/floconsole/floconsole/services/user_service.py
🧰 Additional context used
🧬 Code graph analysis (7)
wavefront/client/src/hooks/data/fetch-hooks.ts (3)
wavefront/client/src/types/user.ts (1)
  • IUser (1-6)
wavefront/client/src/hooks/data/query-keys.ts (1)
  • getUsersKey (110-110)
wavefront/client/src/hooks/data/query-functions.ts (1)
  • getUsersQueryFn (422-422)
wavefront/client/src/pages/apps/[appId]/users/index.tsx (5)
wavefront/client/src/store/notification-store.ts (1)
  • useNotifyStore (32-32)
wavefront/client/src/types/user.ts (1)
  • IUser (1-6)
wavefront/client/src/hooks/data/fetch-hooks.ts (1)
  • useGetUsers (414-416)
wavefront/client/src/hooks/data/query-keys.ts (1)
  • getUsersKey (110-110)
wavefront/client/src/lib/utils.ts (1)
  • extractErrorMessage (21-66)
wavefront/client/src/pages/apps/[appId]/users/CreateUserDialog.tsx (6)
wavefront/client/src/store/notification-store.ts (1)
  • useNotifyStore (32-32)
wavefront/client/src/types/user.ts (2)
  • CreateUserInput (43-43)
  • createUserSchema (11-19)
wavefront/server/modules/api_services_module/api_services_module/models/service.py (1)
  • error (131-143)
wavefront/client/src/lib/utils.ts (1)
  • extractErrorMessage (21-66)
wavefront/client/src/components/ui/dialog.tsx (6)
  • Dialog (111-111)
  • DialogContent (113-113)
  • DialogHeader (116-116)
  • DialogTitle (119-119)
  • DialogDescription (114-114)
  • DialogFooter (115-115)
wavefront/client/src/components/ui/input.tsx (1)
  • Input (22-22)
wavefront/client/src/hooks/data/query-functions.ts (2)
wavefront/client/src/types/user.ts (1)
  • IUser (1-6)
wavefront/client/src/pages/types.ts (1)
  • IUser (73-78)
wavefront/client/src/hooks/data/mutation-functions.ts (1)
wavefront/client/src/types/user.ts (1)
  • IUser (1-6)
wavefront/client/src/types/user.ts (1)
wavefront/client/src/utils/regex.ts (2)
  • emailRegex (2-2)
  • passwordRegex (1-1)
wavefront/client/src/api/user-service.ts (2)
wavefront/client/src/lib/axios.ts (1)
  • IApiResponse (16-16)
wavefront/client/src/types/user.ts (1)
  • IUser (1-6)
🔇 Additional comments (16)
wavefront/server/apps/floconsole/floconsole/services/user_service.py (1)

32-35: LGTM! Good consistency improvement.

Adding refresh=True ensures the returned user object reflects the updated state after soft deletion, aligning with the pattern already used in update_user (line 25) and supporting client-side data refresh requirements.

wavefront/client/src/router/routes.tsx (1)

28-28: LGTM! Standard routing setup.

The new Users route follows the established pattern for resource management pages and is properly nested under the app layout.

Also applies to: 193-196

wavefront/client/src/pages/apps/layout.tsx (1)

7-7: LGTM! Navigation setup is consistent.

The Users navigation item follows the established pattern and appropriately reuses the PermissionIcon component.

Also applies to: 81-87

wavefront/client/src/hooks/data/query-keys.ts (1)

65-66: LGTM! Query key functions follow established patterns.

The new getUsersKey and getUserKey functions are consistent with existing query key builders in this file and follow the correct naming conventions.

wavefront/client/src/hooks/data/query-functions.ts (1)

374-380: LGTM! Query function follows established patterns.

The getUsersQueryFn implementation is consistent with other query functions in this file, properly validates the response structure, and provides a safe fallback.

wavefront/client/src/pages/apps/[appId]/users/CreateUserDialog.tsx (2)

46-56: LGTM! Proper error handling and user feedback.

The submit handler correctly uses extractErrorMessage for consistent error handling and provides appropriate user feedback via notifications. The success flow properly triggers callbacks and closes the dialog.


68-130: Well-structured form with proper validation.

The form fields are properly configured with:

  • Clear labels and required field indicators
  • Appropriate input types (email, password)
  • React Hook Form integration
  • Zod validation via the schema
wavefront/client/src/hooks/data/mutation-hooks.ts (3)

85-103: LGTM! Well-implemented create user hook.

The useCreateUser hook follows the established pattern with proper:

  • Query invalidation on success
  • Error extraction and user-friendly messaging
  • Success notifications

105-126: LGTM! Proper cache invalidation for both list and detail queries.

The useUpdateUser hook correctly invalidates both the users list (getUsersKey) and the specific user (getUserKey) to ensure the UI reflects the updated data.


128-146: LGTM! Consistent delete implementation.

The useDeleteUser hook follows the same solid pattern as the other mutation hooks with appropriate invalidation and error handling.

wavefront/client/src/hooks/data/mutation-functions.ts (3)

71-73: LGTM! Straightforward delete implementation.

The delete function is simple and doesn't assume a specific response structure, which is appropriate for delete operations.


39-50: The response structure in the code is correct. The createUser method returns Promise<IApiResponse<{ user: IUser }>>, where IApiResponse<T> resolves to AxiosResponse<ApiResponse<T>> and ApiResponse<T> is { meta: Meta; data?: T }. This means response.data.data.user correctly accesses the user object. No changes needed.


52-69: No changes needed. The API response structure is correctly accessed.

The updateUser API is correctly typed as Promise<IApiResponse<{ user: IUser }>>, where IApiResponse<T> is AxiosResponse<ApiResponse<T>>. This creates the nested structure: response.data (the ApiResponse wrapper) → response.data.data (the payload { user: IUser }) → response.data.data.user (the IUser object). The code correctly accesses this structure and is consistent with createUser and other mutation functions.

wavefront/client/src/pages/apps/[appId]/users/EditUserDialog.tsx (1)

35-96: LGTM! Well-structured edit dialog with proper change detection.

The component correctly:

  • Resets the form when the dialog opens with new user data
  • Detects changes by comparing each field to the original values
  • Only sends modified fields to the API
  • Prevents empty updates with a user-friendly error message
  • Delegates cache invalidation to the parent via onSuccess callback

The password handling is secure (empty by default) and the trimming logic correctly filters out whitespace-only passwords.

wavefront/client/src/pages/apps/[appId]/users/index.tsx (2)

42-53: Permission logic is well-designed but currently ineffective.

The permission functions correctly implement:

  • Self-editing capability for all users
  • Admin-only deletion with self-deletion prevention (avoiding accidental lockout)

However, these checks are currently compromised by the hardcoded isSuperAdmin = true on line 36-39. Once the critical security issue is resolved, this logic will function correctly.


70-85: LGTM! Proper async operation handling.

The delete handler correctly:

  • Manages loading state throughout the operation
  • Invalidates the query cache after successful deletion
  • Extracts user-friendly error messages
  • Cleans up state in the finally block

Comment on lines +27 to +54
async listUsers(): Promise<IApiResponse<{ users: IUser[] }>> {
return this.http.get('/v1/users');
}

async createUser(data: {
email: string;
password: string;
first_name: string;
last_name: string;
}): Promise<IApiResponse<{ user: IUser }>> {
return this.http.post('/v1/users', data);
}

async updateUser(
userId: string,
data: {
email?: string;
password?: string;
first_name?: string;
last_name?: string;
}
): Promise<IApiResponse<{ user: IUser }>> {
return this.http.patch(`/v1/users/${userId}`, data);
}

async deleteUser(userId: string): Promise<IApiResponse<{ message: string }>> {
return this.http.delete(`/v1/users/${userId}`);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

find wavefront/client -type f -name "*.ts" -o -name "*.js" | grep -E "(http|client|axios|api)" | head -20

Repository: rootflo/wavefront

Length of output: 965


🏁 Script executed:

git ls-files wavefront/client/src/api/ | head -20

Repository: rootflo/wavefront

Length of output: 996


🏁 Script executed:

cat -n wavefront/client/src/api/user-service.ts | head -30

Repository: rootflo/wavefront

Length of output: 1047


🏁 Script executed:

find wavefront/client -type f -name "axios*" -o -name "*http*" | grep -E "\.(ts|js)$" | head -20

Repository: rootflo/wavefront

Length of output: 94


🏁 Script executed:

find wavefront/client/src -type d -name "lib"

Repository: rootflo/wavefront

Length of output: 85


🏁 Script executed:

cat -n wavefront/client/src/lib/axios.ts 2>/dev/null || find wavefront/client -name "axios.ts" -exec cat -n {} \;

Repository: rootflo/wavefront

Length of output: 2331


🏁 Script executed:

cat -n wavefront/client/src/config/env.ts 2>/dev/null || find wavefront/client -name "env.ts" -exec cat -n {} \;

Repository: rootflo/wavefront

Length of output: 709


🏁 Script executed:

rg "VITE_BASE_URL|baseURL" wavefront/client --type ts --type js -A 2 -B 2 | head -50

Repository: rootflo/wavefront

Length of output: 1297


🏁 Script executed:

find wavefront/client -name "*.env*" -o -name ".env" | head -10

Repository: rootflo/wavefront

Length of output: 89


🏁 Script executed:

cat -n wavefront/client/src/main.ts 2>/dev/null || find wavefront/client/src -name "main.ts" -exec cat -n {} \;

Repository: rootflo/wavefront

Length of output: 43


🏁 Script executed:

cat -n wavefront/client/.env.sample

Repository: rootflo/wavefront

Length of output: 282


🏁 Script executed:

find wavefront/client -name "*.env*" -type f -exec cat -n {} \;

Repository: rootflo/wavefront

Length of output: 282


🏁 Script executed:

find wavefront/client -name "*prod*" -o -name "*production*" | grep -E "\.(env|config|ts|js)$"

Repository: rootflo/wavefront

Length of output: 43


🏁 Script executed:

cat -n wavefront/client/vite.config.ts 2>/dev/null || find wavefront/client -name "vite.config.*" -exec cat -n {} \;

Repository: rootflo/wavefront

Length of output: 549


🏁 Script executed:

find wavefront -name "docker*" -o -name "*compose*" | head -10

Repository: rootflo/wavefront

Length of output: 120


🏁 Script executed:

cat -n wavefront/server/docker-compose.yml | head -100

Repository: rootflo/wavefront

Length of output: 933


🏁 Script executed:

find wavefront/server/docker -type f -name "*.env*" -o -name "*.sh" | head -10

Repository: rootflo/wavefront

Length of output: 43


🏁 Script executed:

rg "https://" wavefront/client --type ts --type js | head -20

Repository: rootflo/wavefront

Length of output: 2192


🏁 Script executed:

rg "protocol|https|http" wavefront/client/src/lib/axios.ts

Repository: rootflo/wavefront

Length of output: 43


🏁 Script executed:

find wavefront -name "README*" -o -name "DEPLOYMENT*" | xargs grep -l "HTTPS\|https" 2>/dev/null | head -5

Repository: rootflo/wavefront

Length of output: 156


🏁 Script executed:

grep -i "https\|security\|password" wavefront/README.md | head -20

Repository: rootflo/wavefront

Length of output: 500


🏁 Script executed:

cat -n wavefront/client/public/config.js

Repository: rootflo/wavefront

Length of output: 200


HTTPS is environment-configured but not code-enforced; consider adding runtime validation in production.

The axios instance relies on environment configuration for HTTPS enforcement rather than explicit code-level validation. Local development uses http://localhost:8002 while staging uses https://console.staging.rootflo.ai, but there is no runtime check preventing misconfiguration. Since passwords are transmitted in request bodies for the createUser and updateUser methods, consider adding a guard to validate that the baseURL uses HTTPS in production environments, or document this as an operational requirement.

🤖 Prompt for AI Agents
In @wavefront/client/src/api/user-service.ts around lines 27-54, Add a runtime
guard in user-service.ts to ensure the HTTP client uses HTTPS in production:
detect the runtime environment (e.g., NODE_ENV === "production") and validate
the axios/baseURL used by this.http before sending sensitive requests from
createUser and updateUser; if the baseURL is not HTTPS, throw or reject with a
clear error (or fail-fast during service initialization) so passwords are never
sent over plain HTTP in production. Ensure the check references the existing
this.http or its configured baseURL and runs at service construction or at the
start of createUser/updateUser to prevent accidental insecure transmissions.

Comment on lines +40 to +44
useEffect(() => {
if (!isOpen) {
form.reset();
}
}, [isOpen, form]);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

Remove form from the useEffect dependency array.

Including the form object in the dependency array can cause the effect to run on every render since the form object reference may change. The effect should only run when isOpen changes.

🔎 Proposed fix
  useEffect(() => {
    if (!isOpen) {
      form.reset();
    }
-  }, [isOpen, form]);
+  }, [isOpen, form.reset]);

Even better, use the callback form to avoid the dependency entirely:

  useEffect(() => {
    if (!isOpen) {
      form.reset();
    }
-  }, [isOpen, form]);
+  }, [isOpen]); // eslint-disable-line react-hooks/exhaustive-deps

The second approach is safer since form.reset is stable across renders in react-hook-form v7+.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
useEffect(() => {
if (!isOpen) {
form.reset();
}
}, [isOpen, form]);
useEffect(() => {
if (!isOpen) {
form.reset();
}
}, [isOpen, form.reset]);
🤖 Prompt for AI Agents
In @wavefront/client/src/pages/apps/[appId]/users/CreateUserDialog.tsx around
lines 40-44, Remove the `form` object from the useEffect dependency array so the
effect only runs when `isOpen` changes; update the useEffect wrapping the
`form.reset()` call in CreateUserDialog to depend solely on `isOpen` (or,
alternatively, call `form.reset` via a stable callback provided by
react-hook-form v7+ so no changing `form` reference is required).

Comment on lines +34 to +40
// Determine permissions - placeholder for super admin check
// In a real implementation, this should come from the backend
const isSuperAdmin = useMemo(() => {
// Placeholder: assume all users with access to this page are super admins
// In production, add a dedicated endpoint or include this in whoami response
return true;
}, [currentUser]);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

# First, locate and read the affected file
find . -type f -name "index.tsx" -path "*/users/*" | head -20

Repository: rootflo/wavefront

Length of output: 118


🏁 Script executed:

# Search for files in the apps directory structure
fd -t f "users" | grep -E "index.tsx|users\.tsx" | head -20

Repository: rootflo/wavefront

Length of output: 43


🏁 Script executed:

# List the directory structure to understand the path
find . -type d -name "apps" 2>/dev/null | head -5

Repository: rootflo/wavefront

Length of output: 118


🏁 Script executed:

# Read the file to see the actual implementation
cat -n ./wavefront/client/src/pages/apps/[appId]/users/index.tsx | head -80

Repository: rootflo/wavefront

Length of output: 3793


🏁 Script executed:

# Check authorization in backend - find user management endpoints
find ./wavefront/server -type f \( -name "*.py" -o -name "*.js" -o -name "*.ts" \) | grep -E "(user|auth)" | head -20

Repository: rootflo/wavefront

Length of output: 1665


🏁 Script executed:

# Read the user controller to check authorization
cat -n ./wavefront/server/apps/floconsole/floconsole/controllers/user_controller.py

Repository: rootflo/wavefront

Length of output: 12069


🏁 Script executed:

# Read user service to check authorization logic
cat -n ./wavefront/server/apps/floconsole/floconsole/services/user_service.py

Repository: rootflo/wavefront

Length of output: 1913


🏁 Script executed:

# Check the authorization requirement decorator
cat -n ./wavefront/server/apps/floconsole/floconsole/authorization/require_auth.py

Repository: rootflo/wavefront

Length of output: 6039


🚨 CRITICAL: Multiple authorization bypass vulnerabilities in user management API.

The frontend's hardcoded isSuperAdmin = true allows all users to see edit/delete UI controls, but the actual critical issues are in the backend:

  1. POST /users (create_user) has NO authorization checks—anyone can create users
  2. GET /users (list_users) has NO authorization checks—anyone can list all users
  3. GET /whoami does not return role/super admin status, preventing the frontend from making informed permission decisions

While the PATCH and DELETE endpoints enforce proper backend authorization (users can only edit themselves or super admins can edit anyone), the unprotected create and list operations allow unauthorized access to sensitive user data and account creation.

Required fixes:

  1. Add authorization checks to POST /users and GET /users endpoints to restrict access to super admins only
  2. Include role/super admin status in the whoami endpoint response
  3. Update the frontend's IUser interface to include role information
  4. Replace the hardcoded isSuperAdmin = true with actual role data from the backend
  5. Ensure all user management operations enforce authorization at both frontend and backend levels
🤖 Prompt for AI Agents
In @wavefront/client/src/pages/apps/[appId]/users/index.tsx around lines 34-40,
The backend lacks authorization on create_user (POST /users) and list_users (GET
/users) and whoami doesn't return role info; update the create_user and
list_users handlers to require super-admin privileges (add or call existing auth
middleware/guard that checks is_super_admin on the request user) and ensure they
return 403 for unauthorized callers, modify the whoami handler to include
role/super_admin flags in its response, update the frontend IUser interface to
include role/superAdmin (or equivalent) fields, and replace the hardcoded
isSuperAdmin useMemo in users/index.tsx with a real check against
currentUser.role/currentUser.superAdmin from whoami; ensure both frontend UI
controls and backend endpoints consistently enforce the same super-admin rule.

@vizsatiz vizsatiz merged commit 42c9543 into develop Jan 6, 2026
6 of 7 checks passed
@vizsatiz vizsatiz deleted the feat_console_fe_user_management branch January 6, 2026 10:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants