import { Body, Controller, Delete, Get, Next, Param, Post, Req, Res, UploadedFile, UseInterceptors, } from '@nestjs/common'; import { FileInterceptor } from '@nestjs/platform-express'; import { NextFunction, Request, Response } from 'express'; import { MaintenanceAuthDto, MaintenanceDetectInstallResponseDto, MaintenanceListBackupsResponseDto, MaintenanceLoginDto, MaintenanceStatusResponseDto, SetMaintenanceModeDto, } from 'src/dtos/maintenance.dto'; import { ServerConfigDto } from 'src/dtos/server.dto'; import { ImmichCookie } from 'src/enum'; import { MaintenanceRoute } from 'src/maintenance/maintenance-auth.guard'; import { MaintenanceWorkerService } from 'src/maintenance/maintenance-worker.service'; import { GetLoginDetails } from 'src/middleware/auth.guard'; import { LoggingRepository } from 'src/repositories/logging.repository'; import { LoginDetails } from 'src/services/auth.service'; import { sendFile } from 'src/utils/file'; import { respondWithCookie } from 'src/utils/response'; import { FilenameParamDto } from 'src/validation'; import type { DatabaseBackupController as _DatabaseBackupController } from 'src/controllers/database-backup.controller'; import type { ServerController as _ServerController } from 'src/controllers/server.controller'; @Controller() export class MaintenanceWorkerController { constructor( private logger: LoggingRepository, private service: MaintenanceWorkerService, ) {} /** * {@link _ServerController.getServerConfig } */ @Get('server/config') getServerConfig(): ServerConfigDto { return this.service.getSystemConfig(); } /** * {@link _DatabaseBackupController.listDatabaseBackups} */ @Get('admin/database-backups') @MaintenanceRoute() listDatabaseBackups(): Promise { return this.service.listBackups(); } /** * {@link _DatabaseBackupController.downloadDatabaseBackup} */ @Get('admin/database-backups/:filename') @MaintenanceRoute() async downloadDatabaseBackup( @Param() { filename }: FilenameParamDto, @Res() res: Response, @Next() next: NextFunction, ) { await sendFile(res, next, () => this.service.downloadBackup(filename), this.logger); } /** * {@link _DatabaseBackupController.deleteDatabaseBackup} */ @Delete('admin/database-backups/:filename') @MaintenanceRoute() async deleteDatabaseBackup(@Param() { filename }: FilenameParamDto): Promise { return this.service.deleteBackup(filename); } /** * {@link _DatabaseBackupController.uploadDatabaseBackup} */ @Post('admin/database-backups/upload') @MaintenanceRoute() @UseInterceptors(FileInterceptor('file')) uploadDatabaseBackup( @UploadedFile() file: Express.Multer.File, ): Promise { return this.service.uploadBackup(file); } @Get('admin/maintenance/status') maintenanceStatus(@Req() request: Request): Promise { return this.service.status(request.cookies[ImmichCookie.MaintenanceToken]); } @Get('admin/maintenance/detect-install') detectPriorInstall(): Promise { return this.service.detectPriorInstall(); } @Post('admin/maintenance/login') async maintenanceLogin( @Req() request: Request, @Body() dto: MaintenanceLoginDto, @GetLoginDetails() loginDetails: LoginDetails, @Res({ passthrough: true }) res: Response, ): Promise { const token = dto.token ?? request.cookies[ImmichCookie.MaintenanceToken]; const auth = await this.service.login(token); return respondWithCookie(res, auth, { isSecure: loginDetails.isSecure, values: [{ key: ImmichCookie.MaintenanceToken, value: token }], }); } @Post('admin/maintenance') @MaintenanceRoute() setMaintenanceMode(@Body() dto: SetMaintenanceModeDto): void { void this.service.setAction(dto); } }