API Reference
Relevant source files
The following files were used as context for generating this wiki page:
The Collimator backend is a server-side application built with the NestJS framework. It provides a RESTful API that serves as the backbone for the entire platform, managing data for users, tasks, classes, sessions, and solutions. The API is designed to be efficient and scalable, leveraging NestJS's modular architecture.
This document provides a reference for the API's structure, its documentation generation process via Swagger, authentication mechanisms, and examples of data models and frontend consumption patterns. All information is derived directly from the source code.
Sources: backend/README.md
API Documentation with Swagger
The project uses Swagger (OpenAPI) to generate interactive API documentation. This is configured in the swagger.ts file, which sets up a multi-version documentation interface.
Sources: backend/src/swagger.ts
Swagger Setup
A dedicated function setup configures the Swagger documentation. It creates a main documentation page that lists all available API versions and then sets up individual documentation endpoints for each version. This allows developers to explore different versions of the API from a single entry point.
The setup process can be visualized as follows:
This diagram illustrates the flow of setting up both the main and version-specific Swagger UIs.
Sources: backend/src/swagger.ts:5-10
Multi-Version Support
The API supports multiple versions. The setup function iterates through a list of API_VERSIONS to create a separate Swagger endpoint for each. For example, for a version 1, a dedicated documentation UI is available at /api/v1.
A key feature is the patchDocumentOnRequest function. It dynamically filters the API documentation for each version, ensuring that only the routes relevant to that specific version (e.g., routes starting with /api/v1) are displayed. This is achieved by creating a deep copy of the main Swagger document and removing paths that do not match the current version's prefix.
// backend/src/swagger.ts:40-51
patchDocumentOnRequest: (req, _res, document) => {
// NOTE: Make a deep copy of the original document,
// or it will be modified on subsequent calls!
const copyDocument = JSON.parse(JSON.stringify(document));
for (const route in document.paths) {
if (route.startsWith(`/${API_PREFIX}/${v}`)) {
continue;
}
delete copyDocument.paths[route];
}
return copyDocument;
},
This ensures a clean and version-specific view for developers browsing the API documentation.
Sources: backend/src/swagger.ts:23-53
Authentication
The API handles user authentication through an OpenID Connect (OIDC) flow, which is initiated by the frontend. The backend validates the OIDC idToken to authenticate users.
OIDC Authentication Flow
The authentication process involves the frontend, an OIDC provider, and the Collimator backend.
This diagram shows the sequence of events from the user initiating a login to the frontend receiving a JWT from the backend API.
The frontend uses a hook useAuthenticateUser to send the idToken received from the OIDC provider to the backend. The backend then returns an AuthenticationResponseDto which contains the application's own authentication token.
Sources: frontend/src/pages/login/oidc-redirect.tsx:84-106
E2E Test Authentication
End-to-end tests also interact with the authentication system. The test setup includes starting the backend with specific OIDC configuration, such as the JWK and user info endpoints. A helper function useAdminUser is used to establish an authenticated session for tests requiring admin privileges.
Sources: e2e/helpers.ts:101-106, e2e/tests/users/user-management.spec.ts:20-22
Data Transfer Objects (DTOs)
The API uses Data Transfer Objects (DTOs) to define the shape of data for requests and responses. These are TypeScript classes decorated with decorators from class-validator for validation and @nestjs/swagger for API documentation.
Example: CreateTaskDto
The CreateTaskDto is used when creating a new task. It defines the properties required for a new task, including metadata and associated files.
This diagram shows the structure of the CreateTaskDto and its relation to CreateReferenceSolutionDto.
The DTO includes special properties for file uploads, decorated with @ApiProperty to specify the format as binary in the Swagger UI.
| Property | Type | Description |
|---|---|---|
title | string | The title of the task. |
description | string | The description of the task. |
type | TaskType | The type of the task (e.g., SCRATCH). |
taskFile | Express.Multer.File | The task file itself (e.g., a .sb3 file). |
referenceSolutionsFiles | Express.Multer.File[] | An array of reference solution files. |
referenceSolutions | CreateReferenceSolutionDto[] | An array of reference solution metadata. |
Sources: backend/src/api/tasks/dto/create-task.dto.ts:6-28
The referenceSolutions property is an array of CreateReferenceSolutionDto, and the @Type(() => CreateReferenceSolutionDto) decorator from class-transformer ensures that incoming plain objects are transformed into instances of the CreateReferenceSolutionDto class.
Sources: backend/src/api/tasks/dto/create-task.dto.ts:24-28
Frontend API Consumption
The frontend application uses custom React hooks to interact with the backend API. These hooks typically wrap the useSWR hook for data fetching, caching, and revalidation.
Fetching Solution Data
The file frontend/src/api/collimator/hooks/solutions/useSolution.ts provides hooks for fetching solution data and files.
useSolution: Fetches metadata for a specific student solution.useSolutionFile: Fetches the actual solution file (Blob) based on its hash.useFetchLatestSolutionFile: A callback function to fetch the latest solution file for a student for a given task on demand.
The following diagram illustrates the flow when the frontend requests a solution file.
This diagram shows how a React component uses the useSolutionFile hook, which leverages SWR to fetch a file from the backend and manage the request state.
The hooks construct the API endpoint URL and use a fetcher function to make the request. They handle cases where IDs are not yet available by returning a never-resolving promise to prevent invalid requests.
Sources: frontend/src/api/collimator/hooks/solutions/useSolution.ts:48-73