- File model + migration: file metadata, content lives in object storage - IFileStorage port with local disk and S3-compatible (RustFS/MinIO) adapters - POST /files, GET /files/:id/download, DELETE /files/:id - MIME sniffed from content; only safe images served inline, nosniff header - FileOwnerRegistry: owner modules register to grant visibility and keep their files from GC; FileGcService removes orphaned files hourly - TransformResponseInterceptor passes StreamableFile through Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
25 lines
1.1 KiB
TypeScript
25 lines
1.1 KiB
TypeScript
import { Inject, Injectable } from '@nestjs/common';
|
||
import { FILE_REPOSITORY, type IFileRepository } from '../../../domain/repositories/file.repository.interface.js';
|
||
import { GetFilesQuery } from './get-files.query.js';
|
||
import { FileDto } from '../../dto/file.dto.js';
|
||
import { FileApplicationMapper } from '../../mappers/file-application.mapper.js';
|
||
|
||
/**
|
||
* Метаданные файлов по id — для модулей-владельцев, раскрывающих свои связи
|
||
* в FileDto (по аналогии с GetUsersUseCase). Доступ проверяет вызывающий:
|
||
* он отдаёт только файлы своих сущностей, видимых пользователю.
|
||
*/
|
||
@Injectable()
|
||
export class GetFilesUseCase {
|
||
constructor(
|
||
@Inject(FILE_REPOSITORY)
|
||
private readonly fileRepository: IFileRepository,
|
||
) {}
|
||
|
||
async execute(query: GetFilesQuery): Promise<FileDto[]> {
|
||
const ids = [...new Set(query.ids)];
|
||
const files = await this.fileRepository.findByIds(ids);
|
||
return files.map(FileApplicationMapper.toDto);
|
||
}
|
||
}
|