System Architecture
Core Features
Data Management
Frontend Components
Extensibility
The following files were used as context for generating this wiki page:
The People Directory module provides a robust API for managing members within an organization. It allows for the creation, retrieval, updating, and deletion of individual members, as well as bulk creation operations. This module integrates user management with device management capabilities, enabling the association of members with devices and the ability to unlink or remove specific hosts.
Designed as a NestJS module, it follows a clear separation of concerns, with a controller handling API requests, a service encapsulating business logic, and dedicated utility classes for database queries and data validation. This structure ensures maintainability, scalability, and adherence to best practices for API development.
The People Directory module is structured around the standard NestJS pattern of Controllers, Services, and Modules, augmented by specialized utility classes for database interactions and validation. This layered architecture ensures that business logic is decoupled from HTTP concerns and data access.
PeopleController: Handles incoming HTTP requests, routes them to the appropriate service methods, and formats responses.PeopleService: Contains the core business logic for member management, orchestrating interactions with validators, query helpers, and external services like FleetService.MemberValidator: Provides methods to validate the existence of organizations, users, and member relationships, ensuring data integrity before operations proceed.MemberQueries: Encapsulates all direct database interactions related to members, using Prisma ORM.FleetService: An external dependency used by PeopleService to manage devices (hosts) associated with members in FleetDM.The following diagram illustrates the high-level request flow within the People Directory module:
Sources: apps/api/src/people/people.controller.ts apps/api/src/people/people.service.ts apps/api/src/people/utils/member-validator.ts apps/api/src/people/utils/member-queries.ts
The PeopleController exposes a comprehensive set of RESTful API endpoints for managing organizational members. All endpoints are protected by HybridAuthGuard and require an X-Organization-Id header (or API key authentication).
Sources: apps/api/src/people/people.controller.ts
The PeopleService is the central component for all business logic related to member management. It orchestrates operations by calling MemberValidator for data integrity checks, MemberQueries for database interactions, and FleetService for device management.
Key methods include:
findAllByOrganization(organizationId: string): Retrieves all active members for a given organization.findById(memberId: string, organizationId: string): Fetches a single member by their ID within an organization.create(organizationId: string, createData: CreatePeopleDto): Creates a new member after validating the organization, user, and ensuring the user is not already a member.bulkCreate(organizationId: string, bulkCreateData: BulkCreatePeopleDto): Handles the creation of multiple members, performing individual validations and then a bulk database insert for valid entries. It returns a summary of successful and failed creations.updateById(memberId: string, organizationId: string, updateData: UpdatePeopleDto): Updates an existing member's details. Includes validation for userId changes to prevent duplicate memberships.deleteById(memberId: string, organizationId: string): Deactivates or removes a member from an organization.unlinkDevice(memberId: string, organizationId: string): Disassociates all devices from a member. This involves removing hosts from FleetDM based on the member's fleetDmLabelId and deleting associated Device records from the local database.removeHostById(memberId: string, organizationId: string, hostId: number): Removes a specific host from a member's associated devices in FleetDM.Sources: apps/api/src/people/people.service.ts
The MemberValidator class provides static methods to ensure the validity of entities and relationships before performing operations. This prevents common data integrity issues and provides clear error messages.
validateOrganization(organizationId: string): Checks if an organization with the given ID exists. Throws NotFoundException if not found.validateUser(userId: string): Checks if a user with the given ID exists. Throws NotFoundException if not found.validateMemberExists(memberId: string, organizationId: string): Confirms that a member exists and is active within the specified organization. Throws NotFoundException if not found.validateUserNotMember(userId: string, organizationId: string, excludeMemberId?: string): Ensures that a user is not already an active member of the organization. An optional excludeMemberId allows this check to be used during updates where the member's own ID should be ignored. Throws BadRequestException if the user is already a member.Sources: apps/api/src/people/utils/member-validator.ts
The MemberQueries class acts as a data access layer, abstracting direct Prisma ORM calls for member-related operations. It defines a standard MEMBER_SELECT object to ensure consistent data retrieval across different queries.
MEMBER_SELECT: A constant object defining the fields to be selected when querying member data, including nested user information.findAllByOrganization(organizationId: string): Retrieves all members for an organization, ordered by creation date.findByIdInOrganization(memberId: string, organizationId: string): Finds a specific member by ID within an organization.createMember(organizationId: string, createData: CreatePeopleDto): Inserts a new member record into the database.updateMember(memberId: string, updateData: UpdatePeopleDto): Updates an existing member record. Handles fleetDmLabelId specifically to allow setting it to null.findMemberForDeletion(memberId: string, organizationId: string): Retrieves minimal member and user information specifically for the deletion process.deleteMember(memberId: string): Deletes a member record from the database.unlinkDevice(memberId: string): Updates a member's record by setting fleetDmLabelId to null.bulkCreateMembers(organizationId: string, memberData: CreatePeopleDto[]): Performs a createMany operation for multiple members, then fetches the newly created members for the response. skipDuplicates is used to prevent errors if a user is already a member.Sources: apps/api/src/people/utils/member-queries.ts
The module uses DTOs for defining the structure of data exchanged between the client and the API, ensuring strong typing and validation.
Sources: apps/api/src/people/dto/create-people.dto.ts apps/api/src/people/dto/bulk-create-people.dto.ts
CreatePeopleDtoThis DTO defines the data required to create a single new member.
export class CreatePeopleDto {
userId: string;
role: string;
department?: Departments;
isActive?: boolean;
fleetDmLabelId?: number;
jobTitle?: string;
}Sources: apps/api/src/people/dto/create-people.dto.ts
BulkCreatePeopleDtoThis DTO is used for the bulk creation endpoint and contains an array of CreatePeopleDto objects. It includes validation for array size.
export class BulkCreatePeopleDto {
@IsArray()
@ArrayMinSize(1)
@ArrayMaxSize(1000)
@ValidateNested({ each: true })
@Type(() => CreatePeopleDto)
members: CreatePeopleDto[];
}Sources: apps/api/src/people/dto/bulk-create-people.dto.ts
This sequence diagram illustrates the process of creating a new member through the API.
Sources: apps/api/src/people/people.controller.ts, apps/api/src/people/people.service.ts
This sequence diagram details the process of unlinking devices from a member, which involves interactions with both the local database and the external FleetDM system.
Sources: apps/api/src/people/people.controller.ts, apps/api/src/people/people.service.ts
The PeopleModule is a standard NestJS module that aggregates the PeopleController and PeopleService. It also imports AuthModule for authentication capabilities and provides FleetService as a dependency to PeopleService.
import { Module } from '@nestjs/common';
import { AuthModule } from '../auth/auth.module';
import { FleetService } from '../lib/fleet.service';
import { PeopleController } from './people.controller';
import { PeopleService } from './people.service';
@Module({
imports: [AuthModule],
The module exports PeopleService, making it available for injection into other modules if needed.
Sources: apps/api/src/people/people.module.ts
CreatePeopleDto |
PeopleResponseDto |
| N/A |
POST | /people/bulk | Bulk create multiple members | BulkCreatePeopleDto | { created: [], errors: [], summary: {} } | N/A |
GET | /people/:id | Retrieve a member by ID | N/A | PeopleResponseDto | N/A |
PATCH | /people/:id | Update an existing member | UpdatePeopleDto | PeopleResponseDto | N/A |
DELETE | /people/:id/host/:hostId | Remove a specific host from a member's devices | N/A | { success: true } | owner |
DELETE | /people/:id | Delete a member | N/A | { success: true, deletedMember: {} } | N/A |
PATCH | /people/:id/unlink-device | Unlink all devices from a member | N/A | PeopleResponseDto | N/A |