State Management & Context
Relevant source files
The following files were used as context for generating this wiki page:
The MuteTaxes frontend utilizes React Context API to manage global state across the application. The state management architecture is primarily divided into two main contexts: the AuthContext for user authentication and session management, and the AppContext for application-specific data, specifically the dynamic authorization-based resource list.
These contexts ensure that user credentials, roles, and accessible resources (tables) are consistently available to components throughout the component tree. This architecture supports relationship-based access control by allowing the UI to reactively update based on the permissions returned from the backend.
Sources: frontend/src/App.tsx:24-26, PLAN.md:162-168
Authentication Context (AuthContext)
The AuthContext is the primary mechanism for managing user sessions. It handles login/logout logic, persists the JWT token in localStorage, and provides identity information for the current user.
Core Authentication Flow
The context exposes a login function that interacts with the /auth/login endpoint. Upon successful authentication, the backend returns a JWT and user object, which are then stored locally to maintain the session across page reloads.
Auth State Properties
The following properties are exposed by the useAuth hook:
| Property | Type | Description |
|---|---|---|
user | User | null | The current authenticated user object (id and username). |
token | string | null | The JWT used for authorized API requests. |
isSuperAdmin | boolean | Derived state checking if the user has the "superadmin" role. |
login | function | Handles the authentication request and state update. |
logout | function | Clears local storage and resets the auth state. |
Sources: frontend/src/context/AuthContext.tsx:10-21, frontend/src/context/AuthContext.tsx:55-60
Application Context (AppContext)
The AppContext manages data specific to the CRM's functional requirements, primarily focusing on the resources the current user is permitted to interact with based on OpenFGA checks.
Dynamic Resource Management
The AppContext tracks allowedTables, which is a list of table resources the user has "read" permissions for. This list is used by the Layout component to render the navigation sidebar dynamically.
App State Properties
| Property | Type | Description |
|---|---|---|
allowedTables | Table[] | Array of tables the user is permitted to see. |
loadingTables | boolean | Loading state for the table fetching process. |
refreshAllowedTables | function | Triggers a fresh fetch of allowed tables from the backend. |
Sources: frontend/src/context/AppContext.tsx:8-12, frontend/src/api/endpoints.ts:109-110
Provider Hierarchy & Integration
The application wraps the entire route tree with these providers in App.tsx. The AuthProvider is placed at the top of the hierarchy because the AppProvider (and its underlying API calls) depends on the authentication token.
Component Tree Structure
Sources: frontend/src/App.tsx:24-28
State Interaction in UI Components
- Layout Component: Consumes
AuthContextfor user display/logout andAppContextto render the navigation menu based onallowedTables. - Protected Routes: Use the
useAuthhook withinRequireAuthandSuperAdminRoutecomponents to redirect unauthorized users or restrict access to admin pages (Users, Roles, Permissions). - Table Pages: Use the token from
AuthContextto fetch specific CRUD permissions for the current table slug.
Sources: frontend/src/App.tsx:11-21, frontend/src/components/Layout.tsx:21-25, frontend/src/pages/TablePage.tsx:25-30
Summary
The state management system effectively separates identity management (AuthContext) from resource authorization (AppContext). By centralizing the authentication token and the list of authorized resources, the system ensures that the UI remains a consistent reflection of the underlying OpenFGA relationship model. This enables the "Relationship-Based Access Control" feature where the UI automatically adapts as permissions are modified in the backend.
Sources: PLAN.md:10-14, frontend/src/context/AppContext.tsx:1-35