mirror of
https://github.com/immich-app/immich.git
synced 2026-03-12 21:42:54 -07:00
Compare commits
1 Commits
fix/album-
...
refactor/r
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d2d58c2024 |
@@ -1,5 +1,4 @@
|
||||
import { Body, Controller, Delete, Get, Next, Param, Post, Res, UploadedFile, UseInterceptors } from '@nestjs/common';
|
||||
import { FileInterceptor } from '@nestjs/platform-express';
|
||||
import { Body, Controller, Delete, Get, Next, Param, Post, Res, UseInterceptors } from '@nestjs/common';
|
||||
import { ApiBody, ApiConsumes, ApiTags } from '@nestjs/swagger';
|
||||
import { NextFunction, Response } from 'express';
|
||||
import { Endpoint, HistoryBuilder } from 'src/decorators';
|
||||
@@ -10,6 +9,7 @@ import {
|
||||
} from 'src/dtos/database-backup.dto';
|
||||
import { ApiTag, ImmichCookie, Permission } from 'src/enum';
|
||||
import { Authenticated, FileResponse, GetLoginDetails } from 'src/middleware/auth.guard';
|
||||
import { FileUploadInterceptor } from 'src/middleware/file-upload.interceptor';
|
||||
import { LoggingRepository } from 'src/repositories/logging.repository';
|
||||
import { LoginDetails } from 'src/services/auth.service';
|
||||
import { DatabaseBackupService } from 'src/services/database-backup.service';
|
||||
@@ -91,11 +91,6 @@ export class DatabaseBackupController {
|
||||
description: 'Uploads .sql/.sql.gz file to restore backup from',
|
||||
history: new HistoryBuilder().added('v2.5.0').alpha('v2.5.0'),
|
||||
})
|
||||
@UseInterceptors(FileInterceptor('file'))
|
||||
uploadDatabaseBackup(
|
||||
@UploadedFile()
|
||||
file: Express.Multer.File,
|
||||
): Promise<void> {
|
||||
return this.service.uploadBackup(file);
|
||||
}
|
||||
@UseInterceptors(FileUploadInterceptor)
|
||||
uploadDatabaseBackup() {}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ export enum UploadFieldName {
|
||||
ASSET_DATA = 'assetData',
|
||||
SIDECAR_DATA = 'sidecarData',
|
||||
PROFILE_DATA = 'file',
|
||||
BACKUP_DATA = 'backup',
|
||||
}
|
||||
|
||||
class AssetMediaBase {
|
||||
|
||||
@@ -490,6 +490,7 @@ export enum MetadataKey {
|
||||
export enum RouteKey {
|
||||
Asset = 'assets',
|
||||
User = 'users',
|
||||
DatabaseBackup = 'admin/database-backups',
|
||||
}
|
||||
|
||||
export enum CacheControl {
|
||||
|
||||
@@ -1,17 +1,4 @@
|
||||
import {
|
||||
Body,
|
||||
Controller,
|
||||
Delete,
|
||||
Get,
|
||||
Next,
|
||||
Param,
|
||||
Post,
|
||||
Req,
|
||||
Res,
|
||||
UploadedFile,
|
||||
UseInterceptors,
|
||||
} from '@nestjs/common';
|
||||
import { FileInterceptor } from '@nestjs/platform-express';
|
||||
import { Body, Controller, Delete, Get, Next, Param, Post, Req, Res, UseInterceptors } from '@nestjs/common';
|
||||
import { NextFunction, Request, Response } from 'express';
|
||||
import {
|
||||
MaintenanceAuthDto,
|
||||
@@ -34,6 +21,7 @@ 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';
|
||||
import { DatabaseBackupDeleteDto, DatabaseBackupListResponseDto } from 'src/dtos/database-backup.dto';
|
||||
import { FileUploadInterceptor } from 'src/middleware/file-upload.interceptor';
|
||||
import { DatabaseBackupService } from 'src/services/database-backup.service';
|
||||
|
||||
@Controller()
|
||||
@@ -93,13 +81,8 @@ export class MaintenanceWorkerController {
|
||||
*/
|
||||
@Post('admin/database-backups/upload')
|
||||
@MaintenanceRoute()
|
||||
@UseInterceptors(FileInterceptor('file'))
|
||||
uploadDatabaseBackup(
|
||||
@UploadedFile()
|
||||
file: Express.Multer.File,
|
||||
): Promise<void> {
|
||||
return this.databaseBackupService.uploadBackup(file);
|
||||
}
|
||||
@UseInterceptors(FileUploadInterceptor)
|
||||
uploadDatabaseBackup() {}
|
||||
|
||||
@Get('admin/maintenance/status')
|
||||
maintenanceStatus(@Req() request: Request): Promise<MaintenanceStatusResponseDto> {
|
||||
|
||||
@@ -48,6 +48,7 @@ export class FileUploadInterceptor implements NestInterceptor {
|
||||
private handlers: {
|
||||
userProfile: RequestHandler;
|
||||
assetUpload: RequestHandler;
|
||||
databaseBackup: RequestHandler;
|
||||
};
|
||||
private defaultStorage: StorageEngine;
|
||||
|
||||
@@ -77,6 +78,7 @@ export class FileUploadInterceptor implements NestInterceptor {
|
||||
{ name: UploadFieldName.ASSET_DATA, maxCount: 1 },
|
||||
{ name: UploadFieldName.SIDECAR_DATA, maxCount: 1 },
|
||||
]),
|
||||
databaseBackup: instance.single(UploadFieldName.BACKUP_DATA),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -165,6 +167,10 @@ export class FileUploadInterceptor implements NestInterceptor {
|
||||
return this.handlers.userProfile;
|
||||
}
|
||||
|
||||
case RouteKey.DatabaseBackup: {
|
||||
return this.handlers.databaseBackup;
|
||||
}
|
||||
|
||||
default: {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -86,6 +86,13 @@ export class AssetMediaService extends BaseService {
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case UploadFieldName.BACKUP_DATA: {
|
||||
if (mimeTypes.isBackup(filename)) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this.logger.error(`Unsupported file type ${filename}`);
|
||||
@@ -101,6 +108,7 @@ export class AssetMediaService extends BaseService {
|
||||
[UploadFieldName.ASSET_DATA]: extension,
|
||||
[UploadFieldName.SIDECAR_DATA]: '.xmp',
|
||||
[UploadFieldName.PROFILE_DATA]: extension,
|
||||
[UploadFieldName.BACKUP_DATA]: extension === '.gz' ? '.sql.gz' : extension,
|
||||
};
|
||||
|
||||
return sanitize(`${file.uuid}${lookup[fieldName]}`);
|
||||
@@ -113,6 +121,9 @@ export class AssetMediaService extends BaseService {
|
||||
if (fieldName === UploadFieldName.PROFILE_DATA) {
|
||||
folder = StorageCore.getFolderLocation(StorageFolder.Profile, auth.user.id);
|
||||
}
|
||||
if (fieldName === UploadFieldName.BACKUP_DATA) {
|
||||
folder = StorageCore.getFolderLocation(StorageFolder.Backups, `uploaded-${file.originalName}`);
|
||||
}
|
||||
|
||||
this.storageRepository.mkdirSync(folder);
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { BadRequestException, Injectable, Optional } from '@nestjs/common';
|
||||
import { debounce } from 'lodash';
|
||||
import { DateTime } from 'luxon';
|
||||
import path, { basename } from 'node:path';
|
||||
import path from 'node:path';
|
||||
import { PassThrough, Readable, Writable } from 'node:stream';
|
||||
import { pipeline } from 'node:stream/promises';
|
||||
import semver from 'semver';
|
||||
@@ -252,17 +252,6 @@ export class DatabaseBackupService {
|
||||
return backupFilePath;
|
||||
}
|
||||
|
||||
async uploadBackup(file: Express.Multer.File): Promise<void> {
|
||||
const backupsFolder = StorageCore.getBaseFolder(StorageFolder.Backups);
|
||||
const fn = basename(file.originalname);
|
||||
if (!isValidDatabaseBackupName(fn)) {
|
||||
throw new BadRequestException('Invalid backup name!');
|
||||
}
|
||||
|
||||
const filePath = path.join(backupsFolder, `uploaded-${fn}`);
|
||||
await this.storageRepository.createOrOverwriteFile(filePath, file.buffer);
|
||||
}
|
||||
|
||||
downloadBackup(fileName: string): ImmichFileResponse {
|
||||
if (!isValidDatabaseBackupName(fileName)) {
|
||||
throw new BadRequestException('Invalid backup name!');
|
||||
|
||||
@@ -149,6 +149,7 @@ export const mimeTypes = {
|
||||
isProfile: (filename: string) => isType(filename, profile),
|
||||
isSidecar: (filename: string) => isType(filename, sidecar),
|
||||
isVideo: (filename: string) => isType(filename, video),
|
||||
isBackup: (filename: string) => filename.endsWith('.sql') || filename.endsWith('.sql.gz'),
|
||||
canBeTransparent: (filename: string) => transparentCapableExtensions.has(extname(filename).toLowerCase()),
|
||||
isRaw: (filename: string) => isType(filename, raw),
|
||||
lookup,
|
||||
|
||||
@@ -102,7 +102,7 @@ export const handleUploadDatabaseBackup = async () => {
|
||||
try {
|
||||
const [file] = await openFilePicker({ multiple: false });
|
||||
const formData = new FormData();
|
||||
formData.append('file', file);
|
||||
formData.append('backup', file);
|
||||
|
||||
await uploadRequest<DatabaseBackupUploadDto>({
|
||||
url: getBaseUrl() + '/admin/database-backups/upload',
|
||||
|
||||
Reference in New Issue
Block a user