import { Controller, Delete, Get, HttpCode, HttpStatus, Next, Param, Query, Res } from '@nestjs/common'; import { ApiTags } from '@nestjs/swagger'; import type { NextFunction, Response } from 'express'; import { Endpoint, HistoryBuilder } from 'src/decorators.js'; import type { AuthDto } from 'src/dtos/auth.dto.js'; import { IntegrityGetReportDto, IntegrityReportResponseDto, IntegrityReportSummaryResponseDto, IntegrityReportTypeParamDto, } from 'src/dtos/integrity.dto.js'; import { ApiTag, Permission } from 'src/enum.js'; import { Auth, Authenticated, FileResponse } from 'src/middleware/auth.guard.js'; import { LoggingRepository } from 'src/repositories/logging.repository.js'; import { IntegrityService } from 'src/services/integrity.service.js'; import { sendFile } from 'src/utils/file.js'; import { UUIDv7ParamDto } from 'src/validation.js'; @ApiTags(ApiTag.Maintenance) @Controller('admin/integrity') export class IntegrityAdminController { constructor( private logger: LoggingRepository, private service: IntegrityService, ) {} @Get('summary') @Endpoint({ summary: 'Get integrity report summary', description: 'Get a count of the items flagged in each integrity report', history: new HistoryBuilder().added('v3.0.0').alpha('v3.0.0'), }) @Authenticated({ permission: Permission.Maintenance, admin: true }) getIntegrityReportSummary(): Promise { return this.service.getIntegrityReportSummary(); } @Get('report') @HttpCode(HttpStatus.OK) @Endpoint({ summary: 'Get integrity report by type', description: 'Get all flagged items by integrity report type', history: new HistoryBuilder().added('v3.0.0').alpha('v3.0.0'), }) @Authenticated({ permission: Permission.Maintenance, admin: true }) getIntegrityReport(@Query() dto: IntegrityGetReportDto): Promise { return this.service.getIntegrityReport(dto); } @Get('report/:id/file') @Endpoint({ summary: 'Download flagged file', description: 'Download the untracked/broken file if one exists', history: new HistoryBuilder().added('v3.0.0').alpha('v3.0.0'), }) @FileResponse() @Authenticated({ permission: Permission.Maintenance, admin: true }) async getIntegrityReportFile( @Param() { id }: UUIDv7ParamDto, @Res() res: Response, @Next() next: NextFunction, ): Promise { await sendFile(res, next, () => this.service.getIntegrityReportFile(id), this.logger); } @Delete('report/:id') @Endpoint({ summary: 'Delete integrity report item', description: 'Delete a given report item and perform corresponding deletion (e.g. trash asset, delete file)', history: new HistoryBuilder().added('v3.0.0').alpha('v3.0.0'), }) @Authenticated({ permission: Permission.Maintenance, admin: true }) async deleteIntegrityReport(@Auth() auth: AuthDto, @Param() { id }: UUIDv7ParamDto): Promise { await this.service.deleteIntegrityReport(auth.user.id, id); } @Get('report/:type/csv') @Endpoint({ summary: 'Export integrity report by type as CSV', description: 'Get all integrity report entries for a given type as a CSV', history: new HistoryBuilder().added('v3.0.0').alpha('v3.0.0'), }) @FileResponse() @Authenticated({ permission: Permission.Maintenance, admin: true }) getIntegrityReportCsv(@Param() { type }: IntegrityReportTypeParamDto, @Res() res: Response): void { res.header({ 'Content-Type': 'text/csv', 'Cache-Control': 'private, no-cache, no-transform', 'Content-Disposition': `attachment; filename="${encodeURIComponent(`${Date.now()}-${type}.csv`)}"`, }); this.service.getIntegrityReportCsv(type).pipe(res); } }