Users Management
Relevant source files
The following files were used as context for generating this wiki page:
- packages/api/Modules/Users/UserService.cs
- packages/web/src/features/users/users.schemas.ts
- packages/web/src/routes/_authed/admin/users/index.tsx
- packages/api/Modules/Users/UserEndpoints.cs
- packages/web/src/features/users/users.server.ts
- packages/web/src/features/users/users.functions.ts
- packages/api/Migrations/AppDb/20260513112353_AddUsers.Designer.cs
- packages/web/src/routes/_authed/admin/users/-components/form.tsx
The Users Management module provides the core functionality for managing administrative and standard users within the system. It encompasses user lifecycle operations including creation, retrieval, updates, and archival, alongside a specialized subsystem for managing leave allowances. Sources: packages/api/Modules/Users/UsersModule.cs, packages/web/src/routes/_authed/admin/users/index.tsx
This system is architected as a full-stack feature, utilizing a .NET Minimal API backend with Entity Framework Core and a React-based frontend powered by TanStack Start and TanStack Table. It supports role-based access control with three primary roles: Admin, Client Manager, and User. Sources: packages/web/src/features/users/users.schemas.ts:4-10, packages/api/Modules/Users/UserEndpoints.cs:13-17
Architecture and Data Flow
The module follows a layered architecture where the frontend interacts with the backend through a structured API.
Backend Structure
The backend logic is centered around the UserService, which handles database interactions via AppDbContext. API endpoints are exposed through UserEndpoints.
- UserService: Contains business logic for CRUD operations, searching, and sorting. Sources: packages/api/Modules/Users/UserService.cs:13-25
- UserEndpoints: Maps HTTP routes to service methods and handles authentication claim extraction for self-provisioning. Sources: packages/api/Modules/Users/UserEndpoints.cs:13-35
Frontend Structure
The frontend is organized into schemas, server functions, and UI components.
- Schemas: Define Zod validation and TypeScript types for user data. Sources: packages/web/src/features/users/users.schemas.ts:21-30
- Server Functions: Act as a bridge between the React components and the API client. Sources: packages/web/src/features/users/users.functions.ts:10-40
- Components: Provide the UI for listing (
UserList) and editing (UserForm) users. Sources: packages/web/src/routes/_authed/admin/users/index.tsx:32, packages/web/src/routes/_authed/admin/users/-components/form.tsx:40
User Creation Flow
This diagram illustrates the sequence of creating a new user through the administrative interface.
Data Models
User Schema
The user entity consists of basic profile information and associated metadata.
| Field | Type | Description |
|---|---|---|
| Id | Guid | Unique identifier for the user. |
| Name | String | Full name of the user (Required, Max 200). |
| String | Unique email address (Validated, Max 254). | |
| Role | Enum | One of: Admin, ClientManager, User. |
| IsArchived | Boolean | Soft-deletion flag. |
Sources: packages/api/Migrations/AppDb/20260513112353_AddUsers.Designer.cs:85-115, packages/web/src/features/users/users.schemas.ts:21-26
Leave Allowance Schema
Users have specific leave allowances for different leave types per year.
| Field | Type | Description |
|---|---|---|
| LeaveTypeId | Guid | Reference to the type of leave. |
| Mode | Enum | Limited or Unlimited. |
| TotalDays | Decimal | Total days granted (Precision: 5,1). |
| Year | Integer | The year for which the allowance applies. |
Sources: packages/api/Modules/Users/UserService.cs:64-74, packages/web/src/features/users/users.schemas.ts:14-19
API Endpoints
The UserEndpoints class defines the following RESTful routes under the /api/users prefix:
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/users | List users with search, sort, and pagination. |
| GET | /api/users/me | Get or provision the current authenticated user. |
| GET | /api/users/{id} | Get detailed user information including leaves. |
| POST | /api/users | Create a new user. |
| PUT | /api/users/{id} | Update an existing user and their leave allowances. |
| PATCH | /api/users/{id}/archive | Soft-delete a user. |
| PATCH | /api/users/{id}/unarchive | Restore an archived user. |
Sources: packages/api/Modules/Users/UserEndpoints.cs:13-110
Implementation Details
Searching and Sorting
The UserService implements custom search logic that matches against Name, Email, and role labels. Sorting for roles uses a "logical order" (Admin > Client Manager > User) rather than alphabetical order. Sources: packages/api/Modules/Users/UserService.cs:15-20, 31-48
private static readonly Expression<Func<User, int>> RoleSortKey =
user => user.Role == UserRole.Admin ? 0 : user.Role == UserRole.ClientManager ? 1 : 2;
Sources: packages/api/Modules/Users/UserService.cs:20-21
Leave Allowance Synchronization
When a user is created or updated, the system ensures leave allowances are correctly initialized or synchronized.
- Creation:
SeedLeaveAllowancesAsyncautomatically populates the user's allowances for the current year based on all activeLeaveTypes. Sources: packages/api/Modules/Users/UserService.cs:192-212 - Updates: The
UpdateAsyncmethod compares incoming leave requests with existing records, performing a delta update (Insert new, Update existing, Delete missing). Sources: packages/api/Modules/Users/UserService.cs:119-159
Frontend Validation
The web interface uses tanstack/react-form combined with zod for real-time validation. Sources: packages/web/src/routes/_authed/admin/users/-components/form.tsx:44-55
export const userSchema = z.object({
name: z.string().trim().min(1, 'Name is required'),
email: z.string().email('Must be a valid email'),
role: z.enum(userRoles, { message: 'Role is required' }),
leaves: z.array(userLeaveAllowanceSchema),
});
Sources: packages/web/src/features/users/users.schemas.ts:21-26
Summary
The Users Management system provides a robust framework for handling user identity and administrative configuration. By integrating leave allowances directly into the user update flow and utilizing logical sorting for roles, it offers a tailored experience for organizational administration. The implementation ensures data integrity through unique email constraints and comprehensive validation across both backend and frontend layers.