Summary
The MoodleController (proxy endpoints) forwards raw Moodle API responses directly to the caller. Additionally, GET /moodle/sync/history uses raw @Query parameters for pagination without a validation DTO.
Affected Endpoints
Raw response passthrough (no DTOs)
| Endpoint |
Currently Returns |
POST /moodle/login |
Raw Moodle token response |
POST /moodle/get-site-info |
Raw Moodle site info object |
POST /moodle/get-enrolled-courses |
Raw Moodle course array |
POST /moodle/get-enrolled-users-by-course |
Raw Moodle user array |
POST /moodle/get-course-user-profiles |
Raw Moodle user profiles |
POST /moodle/get-moodle-courses |
Raw Moodle courses |
POST /moodle/get-course-categories |
Raw Moodle categories |
These endpoints (moodle.controller.ts) forward raw upstream responses. If the Moodle API adds, removes, or renames fields, the change propagates silently to the frontend.
Missing pagination query DTO
GET /moodle/sync/history (moodle-sync.controller.ts:157-159) uses raw @Query('page') and @Query('limit') with manual Number() conversion in the controller body instead of a validated query DTO. This means:
- Non-numeric strings pass through without rejection (e.g.,
?page=abc)
- Negative values are only clamped by
Math.max/Math.min, not validated
Impact
- Proxy endpoints: Moodle API shape changes silently break the frontend. No control over which fields are exposed.
- Pagination: Invalid query params are silently coerced instead of returning 400.
Implementation Notes
Proxy endpoints
- Determine which Moodle response fields the frontend actually uses and create typed response DTOs that pick only those fields.
- Alternatively, if these endpoints are only used for development/debugging and not consumed by the frontend, consider whether they should be gated behind an env flag or removed.
Pagination DTO
- The codebase already has a pagination pattern in other modules (e.g.,
ListDimensionsQueryDto, ListFacultyQueryDto) with @Type(() => Number), @IsInt(), @Min(1).
- Extract a shared
PaginationQueryDto (see also: enrollments module has the same issue) or create a module-local one.
- Replace the raw
@Query('page') and @Query('limit') with @Query() query: SyncHistoryQueryDto.
Acceptance Criteria
Summary
The
MoodleController(proxy endpoints) forwards raw Moodle API responses directly to the caller. Additionally,GET /moodle/sync/historyuses raw@Queryparameters for pagination without a validation DTO.Affected Endpoints
Raw response passthrough (no DTOs)
POST /moodle/loginPOST /moodle/get-site-infoPOST /moodle/get-enrolled-coursesPOST /moodle/get-enrolled-users-by-coursePOST /moodle/get-course-user-profilesPOST /moodle/get-moodle-coursesPOST /moodle/get-course-categoriesThese endpoints (
moodle.controller.ts) forward raw upstream responses. If the Moodle API adds, removes, or renames fields, the change propagates silently to the frontend.Missing pagination query DTO
GET /moodle/sync/history(moodle-sync.controller.ts:157-159) uses raw@Query('page')and@Query('limit')with manualNumber()conversion in the controller body instead of a validated query DTO. This means:?page=abc)Math.max/Math.min, not validatedImpact
Implementation Notes
Proxy endpoints
Pagination DTO
ListDimensionsQueryDto,ListFacultyQueryDto) with@Type(() => Number),@IsInt(),@Min(1).PaginationQueryDto(see also: enrollments module has the same issue) or create a module-local one.@Query('page')and@Query('limit')with@Query() query: SyncHistoryQueryDto.Acceptance Criteria
GET /moodle/sync/historyuses a validated query DTO for pagination.