mirror of
https://github.com/immich-app/immich.git
synced 2025-06-03 05:36:44 -04:00
refactor(server): make storage core singleton (#4608)
This commit is contained in:
parent
2288b022bc
commit
6b25435b4f
@ -10,8 +10,6 @@ import {
|
|||||||
newCommunicationRepositoryMock,
|
newCommunicationRepositoryMock,
|
||||||
newCryptoRepositoryMock,
|
newCryptoRepositoryMock,
|
||||||
newJobRepositoryMock,
|
newJobRepositoryMock,
|
||||||
newMoveRepositoryMock,
|
|
||||||
newPersonRepositoryMock,
|
|
||||||
newStorageRepositoryMock,
|
newStorageRepositoryMock,
|
||||||
newSystemConfigRepositoryMock,
|
newSystemConfigRepositoryMock,
|
||||||
} from '@test';
|
} from '@test';
|
||||||
@ -25,8 +23,6 @@ import {
|
|||||||
ICommunicationRepository,
|
ICommunicationRepository,
|
||||||
ICryptoRepository,
|
ICryptoRepository,
|
||||||
IJobRepository,
|
IJobRepository,
|
||||||
IMoveRepository,
|
|
||||||
IPersonRepository,
|
|
||||||
IStorageRepository,
|
IStorageRepository,
|
||||||
ISystemConfigRepository,
|
ISystemConfigRepository,
|
||||||
JobItem,
|
JobItem,
|
||||||
@ -165,8 +161,6 @@ describe(AssetService.name, () => {
|
|||||||
let assetMock: jest.Mocked<IAssetRepository>;
|
let assetMock: jest.Mocked<IAssetRepository>;
|
||||||
let cryptoMock: jest.Mocked<ICryptoRepository>;
|
let cryptoMock: jest.Mocked<ICryptoRepository>;
|
||||||
let jobMock: jest.Mocked<IJobRepository>;
|
let jobMock: jest.Mocked<IJobRepository>;
|
||||||
let moveMock: jest.Mocked<IMoveRepository>;
|
|
||||||
let personMock: jest.Mocked<IPersonRepository>;
|
|
||||||
let storageMock: jest.Mocked<IStorageRepository>;
|
let storageMock: jest.Mocked<IStorageRepository>;
|
||||||
let communicationMock: jest.Mocked<ICommunicationRepository>;
|
let communicationMock: jest.Mocked<ICommunicationRepository>;
|
||||||
let configMock: jest.Mocked<ISystemConfigRepository>;
|
let configMock: jest.Mocked<ISystemConfigRepository>;
|
||||||
@ -181,21 +175,9 @@ describe(AssetService.name, () => {
|
|||||||
communicationMock = newCommunicationRepositoryMock();
|
communicationMock = newCommunicationRepositoryMock();
|
||||||
cryptoMock = newCryptoRepositoryMock();
|
cryptoMock = newCryptoRepositoryMock();
|
||||||
jobMock = newJobRepositoryMock();
|
jobMock = newJobRepositoryMock();
|
||||||
moveMock = newMoveRepositoryMock();
|
|
||||||
personMock = newPersonRepositoryMock();
|
|
||||||
storageMock = newStorageRepositoryMock();
|
storageMock = newStorageRepositoryMock();
|
||||||
configMock = newSystemConfigRepositoryMock();
|
configMock = newSystemConfigRepositoryMock();
|
||||||
sut = new AssetService(
|
sut = new AssetService(accessMock, assetMock, cryptoMock, jobMock, configMock, storageMock, communicationMock);
|
||||||
accessMock,
|
|
||||||
assetMock,
|
|
||||||
cryptoMock,
|
|
||||||
jobMock,
|
|
||||||
configMock,
|
|
||||||
moveMock,
|
|
||||||
personMock,
|
|
||||||
storageMock,
|
|
||||||
communicationMock,
|
|
||||||
);
|
|
||||||
|
|
||||||
when(assetMock.getById)
|
when(assetMock.getById)
|
||||||
.calledWith(assetStub.livePhotoStillAsset.id)
|
.calledWith(assetStub.livePhotoStillAsset.id)
|
||||||
|
@ -16,8 +16,6 @@ import {
|
|||||||
ICommunicationRepository,
|
ICommunicationRepository,
|
||||||
ICryptoRepository,
|
ICryptoRepository,
|
||||||
IJobRepository,
|
IJobRepository,
|
||||||
IMoveRepository,
|
|
||||||
IPersonRepository,
|
|
||||||
IStorageRepository,
|
IStorageRepository,
|
||||||
ISystemConfigRepository,
|
ISystemConfigRepository,
|
||||||
ImmichReadStream,
|
ImmichReadStream,
|
||||||
@ -76,7 +74,6 @@ export class AssetService {
|
|||||||
private logger = new Logger(AssetService.name);
|
private logger = new Logger(AssetService.name);
|
||||||
private access: AccessCore;
|
private access: AccessCore;
|
||||||
private configCore: SystemConfigCore;
|
private configCore: SystemConfigCore;
|
||||||
private storageCore: StorageCore;
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(IAccessRepository) accessRepository: IAccessRepository,
|
@Inject(IAccessRepository) accessRepository: IAccessRepository,
|
||||||
@ -84,14 +81,11 @@ export class AssetService {
|
|||||||
@Inject(ICryptoRepository) private cryptoRepository: ICryptoRepository,
|
@Inject(ICryptoRepository) private cryptoRepository: ICryptoRepository,
|
||||||
@Inject(IJobRepository) private jobRepository: IJobRepository,
|
@Inject(IJobRepository) private jobRepository: IJobRepository,
|
||||||
@Inject(ISystemConfigRepository) configRepository: ISystemConfigRepository,
|
@Inject(ISystemConfigRepository) configRepository: ISystemConfigRepository,
|
||||||
@Inject(IMoveRepository) moveRepository: IMoveRepository,
|
|
||||||
@Inject(IPersonRepository) personRepository: IPersonRepository,
|
|
||||||
@Inject(IStorageRepository) private storageRepository: IStorageRepository,
|
@Inject(IStorageRepository) private storageRepository: IStorageRepository,
|
||||||
@Inject(ICommunicationRepository) private communicationRepository: ICommunicationRepository,
|
@Inject(ICommunicationRepository) private communicationRepository: ICommunicationRepository,
|
||||||
) {
|
) {
|
||||||
this.access = AccessCore.create(accessRepository);
|
this.access = AccessCore.create(accessRepository);
|
||||||
this.configCore = SystemConfigCore.create(configRepository);
|
this.configCore = SystemConfigCore.create(configRepository);
|
||||||
this.storageCore = new StorageCore(storageRepository, assetRepository, moveRepository, personRepository);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
canUploadFile({ authUser, fieldName, file }: UploadRequest): true {
|
canUploadFile({ authUser, fieldName, file }: UploadRequest): true {
|
||||||
@ -147,9 +141,9 @@ export class AssetService {
|
|||||||
getUploadFolder({ authUser, fieldName }: UploadRequest): string {
|
getUploadFolder({ authUser, fieldName }: UploadRequest): string {
|
||||||
authUser = this.access.requireUploadAccess(authUser);
|
authUser = this.access.requireUploadAccess(authUser);
|
||||||
|
|
||||||
let folder = this.storageCore.getFolderLocation(StorageFolder.UPLOAD, authUser.id);
|
let folder = StorageCore.getFolderLocation(StorageFolder.UPLOAD, authUser.id);
|
||||||
if (fieldName === UploadFieldName.PROFILE_DATA) {
|
if (fieldName === UploadFieldName.PROFILE_DATA) {
|
||||||
folder = this.storageCore.getFolderLocation(StorageFolder.PROFILE, authUser.id);
|
folder = StorageCore.getFolderLocation(StorageFolder.PROFILE, authUser.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.storageRepository.mkdirSync(folder);
|
this.storageRepository.mkdirSync(folder);
|
||||||
|
@ -44,7 +44,7 @@ export class MediaService {
|
|||||||
@Inject(IMoveRepository) moveRepository: IMoveRepository,
|
@Inject(IMoveRepository) moveRepository: IMoveRepository,
|
||||||
) {
|
) {
|
||||||
this.configCore = SystemConfigCore.create(configRepository);
|
this.configCore = SystemConfigCore.create(configRepository);
|
||||||
this.storageCore = new StorageCore(this.storageRepository, assetRepository, moveRepository, personRepository);
|
this.storageCore = StorageCore.create(assetRepository, moveRepository, personRepository, storageRepository);
|
||||||
}
|
}
|
||||||
|
|
||||||
async handleQueueGenerateThumbnails({ force }: IBaseJob) {
|
async handleQueueGenerateThumbnails({ force }: IBaseJob) {
|
||||||
@ -140,7 +140,7 @@ export class MediaService {
|
|||||||
const { thumbnail, ffmpeg } = await this.configCore.getConfig();
|
const { thumbnail, ffmpeg } = await this.configCore.getConfig();
|
||||||
const size = format === 'jpeg' ? thumbnail.jpegSize : thumbnail.webpSize;
|
const size = format === 'jpeg' ? thumbnail.jpegSize : thumbnail.webpSize;
|
||||||
const path =
|
const path =
|
||||||
format === 'jpeg' ? this.storageCore.getLargeThumbnailPath(asset) : this.storageCore.getSmallThumbnailPath(asset);
|
format === 'jpeg' ? StorageCore.getLargeThumbnailPath(asset) : StorageCore.getSmallThumbnailPath(asset);
|
||||||
this.storageCore.ensureFolders(path);
|
this.storageCore.ensureFolders(path);
|
||||||
|
|
||||||
switch (asset.type) {
|
switch (asset.type) {
|
||||||
@ -220,7 +220,7 @@ export class MediaService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const input = asset.originalPath;
|
const input = asset.originalPath;
|
||||||
const output = this.storageCore.getEncodedVideoPath(asset);
|
const output = StorageCore.getEncodedVideoPath(asset);
|
||||||
this.storageCore.ensureFolders(output);
|
this.storageCore.ensureFolders(output);
|
||||||
|
|
||||||
const { videoStreams, audioStreams, format } = await this.mediaRepository.probe(input);
|
const { videoStreams, audioStreams, format } = await this.mediaRepository.probe(input);
|
||||||
|
@ -80,7 +80,7 @@ export class MetadataService {
|
|||||||
@Inject(IPersonRepository) personRepository: IPersonRepository,
|
@Inject(IPersonRepository) personRepository: IPersonRepository,
|
||||||
) {
|
) {
|
||||||
this.configCore = SystemConfigCore.create(configRepository);
|
this.configCore = SystemConfigCore.create(configRepository);
|
||||||
this.storageCore = new StorageCore(storageRepository, assetRepository, moveRepository, personRepository);
|
this.storageCore = StorageCore.create(assetRepository, moveRepository, personRepository, storageRepository);
|
||||||
this.configCore.config$.subscribe(() => this.init());
|
this.configCore.config$.subscribe(() => this.init());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -294,7 +294,7 @@ export class MetadataService {
|
|||||||
});
|
});
|
||||||
const checksum = this.cryptoRepository.hashSha1(video);
|
const checksum = this.cryptoRepository.hashSha1(video);
|
||||||
|
|
||||||
const motionPath = this.storageCore.getAndroidMotionPath(asset);
|
const motionPath = StorageCore.getAndroidMotionPath(asset);
|
||||||
this.storageCore.ensureFolders(motionPath);
|
this.storageCore.ensureFolders(motionPath);
|
||||||
|
|
||||||
let motionAsset = await this.assetRepository.getByChecksum(asset.ownerId, checksum);
|
let motionAsset = await this.assetRepository.getByChecksum(asset.ownerId, checksum);
|
||||||
|
@ -58,7 +58,7 @@ export class PersonService {
|
|||||||
) {
|
) {
|
||||||
this.access = AccessCore.create(accessRepository);
|
this.access = AccessCore.create(accessRepository);
|
||||||
this.configCore = SystemConfigCore.create(configRepository);
|
this.configCore = SystemConfigCore.create(configRepository);
|
||||||
this.storageCore = new StorageCore(storageRepository, assetRepository, moveRepository, repository);
|
this.storageCore = StorageCore.create(assetRepository, moveRepository, repository, storageRepository);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getAll(authUser: AuthUserDto, dto: PersonSearchDto): Promise<PeopleResponseDto> {
|
async getAll(authUser: AuthUserDto, dto: PersonSearchDto): Promise<PeopleResponseDto> {
|
||||||
@ -309,7 +309,7 @@ export class PersonService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.logger.verbose(`Cropping face for person: ${personId}`);
|
this.logger.verbose(`Cropping face for person: ${personId}`);
|
||||||
const thumbnailPath = this.storageCore.getPersonThumbnailPath(person);
|
const thumbnailPath = StorageCore.getPersonThumbnailPath(person);
|
||||||
this.storageCore.ensureFolders(thumbnailPath);
|
this.storageCore.ensureFolders(thumbnailPath);
|
||||||
|
|
||||||
const halfWidth = (x2 - x1) / 2;
|
const halfWidth = (x2 - x1) / 2;
|
||||||
|
@ -52,7 +52,7 @@ export class StorageTemplateService {
|
|||||||
this.configCore = SystemConfigCore.create(configRepository);
|
this.configCore = SystemConfigCore.create(configRepository);
|
||||||
this.configCore.addValidator((config) => this.validate(config));
|
this.configCore.addValidator((config) => this.validate(config));
|
||||||
this.configCore.config$.subscribe((config) => this.onConfig(config));
|
this.configCore.config$.subscribe((config) => this.onConfig(config));
|
||||||
this.storageCore = new StorageCore(storageRepository, assetRepository, moveRepository, personRepository);
|
this.storageCore = StorageCore.create(assetRepository, moveRepository, personRepository, storageRepository);
|
||||||
}
|
}
|
||||||
|
|
||||||
async handleMigrationSingle({ id }: IEntityJob) {
|
async handleMigrationSingle({ id }: IEntityJob) {
|
||||||
@ -99,7 +99,7 @@ export class StorageTemplateService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async moveAsset(asset: AssetEntity, metadata: MoveAssetMetadata) {
|
async moveAsset(asset: AssetEntity, metadata: MoveAssetMetadata) {
|
||||||
if (asset.isReadOnly || asset.isExternal || this.storageCore.isAndroidMotionPath(asset.originalPath)) {
|
if (asset.isReadOnly || asset.isExternal || StorageCore.isAndroidMotionPath(asset.originalPath)) {
|
||||||
// External assets are not affected by storage template
|
// External assets are not affected by storage template
|
||||||
// TODO: shouldn't this only apply to external assets?
|
// TODO: shouldn't this only apply to external assets?
|
||||||
return;
|
return;
|
||||||
@ -131,7 +131,7 @@ export class StorageTemplateService {
|
|||||||
const source = asset.originalPath;
|
const source = asset.originalPath;
|
||||||
const ext = path.extname(source).split('.').pop() as string;
|
const ext = path.extname(source).split('.').pop() as string;
|
||||||
const sanitized = sanitize(path.basename(filename, `.${ext}`));
|
const sanitized = sanitize(path.basename(filename, `.${ext}`));
|
||||||
const rootPath = this.storageCore.getLibraryFolder({ id: asset.ownerId, storageLabel });
|
const rootPath = StorageCore.getLibraryFolder({ id: asset.ownerId, storageLabel });
|
||||||
const storagePath = this.render(this.storageTemplate, asset, sanitized, ext);
|
const storagePath = this.render(this.storageTemplate, asset, sanitized, ext);
|
||||||
const fullPath = path.normalize(path.join(rootPath, storagePath));
|
const fullPath = path.normalize(path.join(rootPath, storagePath));
|
||||||
let destination = `${fullPath}.${ext}`;
|
let destination = `${fullPath}.${ext}`;
|
||||||
|
@ -21,21 +21,40 @@ export interface MoveRequest {
|
|||||||
|
|
||||||
type GeneratedAssetPath = AssetPathType.JPEG_THUMBNAIL | AssetPathType.WEBP_THUMBNAIL | AssetPathType.ENCODED_VIDEO;
|
type GeneratedAssetPath = AssetPathType.JPEG_THUMBNAIL | AssetPathType.WEBP_THUMBNAIL | AssetPathType.ENCODED_VIDEO;
|
||||||
|
|
||||||
|
let instance: StorageCore | null;
|
||||||
|
|
||||||
export class StorageCore {
|
export class StorageCore {
|
||||||
private logger = new Logger(StorageCore.name);
|
private logger = new Logger(StorageCore.name);
|
||||||
|
|
||||||
constructor(
|
private constructor(
|
||||||
private repository: IStorageRepository,
|
|
||||||
private assetRepository: IAssetRepository,
|
private assetRepository: IAssetRepository,
|
||||||
private moveRepository: IMoveRepository,
|
private moveRepository: IMoveRepository,
|
||||||
private personRepository: IPersonRepository,
|
private personRepository: IPersonRepository,
|
||||||
|
private repository: IStorageRepository,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
getFolderLocation(folder: StorageFolder, userId: string) {
|
static create(
|
||||||
|
assetRepository: IAssetRepository,
|
||||||
|
moveRepository: IMoveRepository,
|
||||||
|
personRepository: IPersonRepository,
|
||||||
|
repository: IStorageRepository,
|
||||||
|
) {
|
||||||
|
if (!instance) {
|
||||||
|
instance = new StorageCore(assetRepository, moveRepository, personRepository, repository);
|
||||||
|
}
|
||||||
|
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
static reset() {
|
||||||
|
instance = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
static getFolderLocation(folder: StorageFolder, userId: string) {
|
||||||
return join(StorageCore.getBaseFolder(folder), userId);
|
return join(StorageCore.getBaseFolder(folder), userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
getLibraryFolder(user: { storageLabel: string | null; id: string }) {
|
static getLibraryFolder(user: { storageLabel: string | null; id: string }) {
|
||||||
return join(StorageCore.getBaseFolder(StorageFolder.LIBRARY), user.storageLabel || user.id);
|
return join(StorageCore.getBaseFolder(StorageFolder.LIBRARY), user.storageLabel || user.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,27 +62,27 @@ export class StorageCore {
|
|||||||
return join(APP_MEDIA_LOCATION, folder);
|
return join(APP_MEDIA_LOCATION, folder);
|
||||||
}
|
}
|
||||||
|
|
||||||
getPersonThumbnailPath(person: PersonEntity) {
|
static getPersonThumbnailPath(person: PersonEntity) {
|
||||||
return this.getNestedPath(StorageFolder.THUMBNAILS, person.ownerId, `${person.id}.jpeg`);
|
return StorageCore.getNestedPath(StorageFolder.THUMBNAILS, person.ownerId, `${person.id}.jpeg`);
|
||||||
}
|
}
|
||||||
|
|
||||||
getLargeThumbnailPath(asset: AssetEntity) {
|
static getLargeThumbnailPath(asset: AssetEntity) {
|
||||||
return this.getNestedPath(StorageFolder.THUMBNAILS, asset.ownerId, `${asset.id}.jpeg`);
|
return StorageCore.getNestedPath(StorageFolder.THUMBNAILS, asset.ownerId, `${asset.id}.jpeg`);
|
||||||
}
|
}
|
||||||
|
|
||||||
getSmallThumbnailPath(asset: AssetEntity) {
|
static getSmallThumbnailPath(asset: AssetEntity) {
|
||||||
return this.getNestedPath(StorageFolder.THUMBNAILS, asset.ownerId, `${asset.id}.webp`);
|
return StorageCore.getNestedPath(StorageFolder.THUMBNAILS, asset.ownerId, `${asset.id}.webp`);
|
||||||
}
|
}
|
||||||
|
|
||||||
getEncodedVideoPath(asset: AssetEntity) {
|
static getEncodedVideoPath(asset: AssetEntity) {
|
||||||
return this.getNestedPath(StorageFolder.ENCODED_VIDEO, asset.ownerId, `${asset.id}.mp4`);
|
return StorageCore.getNestedPath(StorageFolder.ENCODED_VIDEO, asset.ownerId, `${asset.id}.mp4`);
|
||||||
}
|
}
|
||||||
|
|
||||||
getAndroidMotionPath(asset: AssetEntity) {
|
static getAndroidMotionPath(asset: AssetEntity) {
|
||||||
return this.getNestedPath(StorageFolder.ENCODED_VIDEO, asset.ownerId, `${asset.id}-MP.mp4`);
|
return StorageCore.getNestedPath(StorageFolder.ENCODED_VIDEO, asset.ownerId, `${asset.id}-MP.mp4`);
|
||||||
}
|
}
|
||||||
|
|
||||||
isAndroidMotionPath(originalPath: string) {
|
static isAndroidMotionPath(originalPath: string) {
|
||||||
return originalPath.startsWith(StorageCore.getBaseFolder(StorageFolder.ENCODED_VIDEO));
|
return originalPath.startsWith(StorageCore.getBaseFolder(StorageFolder.ENCODED_VIDEO));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,15 +94,25 @@ export class StorageCore {
|
|||||||
const { id: entityId, resizePath, webpPath, encodedVideoPath } = asset;
|
const { id: entityId, resizePath, webpPath, encodedVideoPath } = asset;
|
||||||
switch (pathType) {
|
switch (pathType) {
|
||||||
case AssetPathType.JPEG_THUMBNAIL:
|
case AssetPathType.JPEG_THUMBNAIL:
|
||||||
return this.moveFile({ entityId, pathType, oldPath: resizePath, newPath: this.getLargeThumbnailPath(asset) });
|
return this.moveFile({
|
||||||
|
entityId,
|
||||||
|
pathType,
|
||||||
|
oldPath: resizePath,
|
||||||
|
newPath: StorageCore.getLargeThumbnailPath(asset),
|
||||||
|
});
|
||||||
case AssetPathType.WEBP_THUMBNAIL:
|
case AssetPathType.WEBP_THUMBNAIL:
|
||||||
return this.moveFile({ entityId, pathType, oldPath: webpPath, newPath: this.getSmallThumbnailPath(asset) });
|
return this.moveFile({
|
||||||
|
entityId,
|
||||||
|
pathType,
|
||||||
|
oldPath: webpPath,
|
||||||
|
newPath: StorageCore.getSmallThumbnailPath(asset),
|
||||||
|
});
|
||||||
case AssetPathType.ENCODED_VIDEO:
|
case AssetPathType.ENCODED_VIDEO:
|
||||||
return this.moveFile({
|
return this.moveFile({
|
||||||
entityId,
|
entityId,
|
||||||
pathType,
|
pathType,
|
||||||
oldPath: encodedVideoPath,
|
oldPath: encodedVideoPath,
|
||||||
newPath: this.getEncodedVideoPath(asset),
|
newPath: StorageCore.getEncodedVideoPath(asset),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -96,7 +125,7 @@ export class StorageCore {
|
|||||||
entityId,
|
entityId,
|
||||||
pathType,
|
pathType,
|
||||||
oldPath: thumbnailPath,
|
oldPath: thumbnailPath,
|
||||||
newPath: this.getPersonThumbnailPath(person),
|
newPath: StorageCore.getPersonThumbnailPath(person),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -159,7 +188,12 @@ export class StorageCore {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private getNestedPath(folder: StorageFolder, ownerId: string, filename: string): string {
|
private static getNestedPath(folder: StorageFolder, ownerId: string, filename: string): string {
|
||||||
return join(this.getFolderLocation(folder, ownerId), filename.substring(0, 2), filename.substring(2, 4), filename);
|
return join(
|
||||||
|
StorageCore.getFolderLocation(folder, ownerId),
|
||||||
|
filename.substring(0, 2),
|
||||||
|
filename.substring(2, 4),
|
||||||
|
filename,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,8 +11,6 @@ import {
|
|||||||
newCryptoRepositoryMock,
|
newCryptoRepositoryMock,
|
||||||
newJobRepositoryMock,
|
newJobRepositoryMock,
|
||||||
newLibraryRepositoryMock,
|
newLibraryRepositoryMock,
|
||||||
newMoveRepositoryMock,
|
|
||||||
newPersonRepositoryMock,
|
|
||||||
newStorageRepositoryMock,
|
newStorageRepositoryMock,
|
||||||
newUserRepositoryMock,
|
newUserRepositoryMock,
|
||||||
userStub,
|
userStub,
|
||||||
@ -26,8 +24,6 @@ import {
|
|||||||
ICryptoRepository,
|
ICryptoRepository,
|
||||||
IJobRepository,
|
IJobRepository,
|
||||||
ILibraryRepository,
|
ILibraryRepository,
|
||||||
IMoveRepository,
|
|
||||||
IPersonRepository,
|
|
||||||
IStorageRepository,
|
IStorageRepository,
|
||||||
IUserRepository,
|
IUserRepository,
|
||||||
} from '../repositories';
|
} from '../repositories';
|
||||||
@ -139,8 +135,6 @@ describe(UserService.name, () => {
|
|||||||
let assetMock: jest.Mocked<IAssetRepository>;
|
let assetMock: jest.Mocked<IAssetRepository>;
|
||||||
let jobMock: jest.Mocked<IJobRepository>;
|
let jobMock: jest.Mocked<IJobRepository>;
|
||||||
let libraryMock: jest.Mocked<ILibraryRepository>;
|
let libraryMock: jest.Mocked<ILibraryRepository>;
|
||||||
let moveMock: jest.Mocked<IMoveRepository>;
|
|
||||||
let personMock: jest.Mocked<IPersonRepository>;
|
|
||||||
let storageMock: jest.Mocked<IStorageRepository>;
|
let storageMock: jest.Mocked<IStorageRepository>;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
@ -149,22 +143,10 @@ describe(UserService.name, () => {
|
|||||||
cryptoRepositoryMock = newCryptoRepositoryMock();
|
cryptoRepositoryMock = newCryptoRepositoryMock();
|
||||||
jobMock = newJobRepositoryMock();
|
jobMock = newJobRepositoryMock();
|
||||||
libraryMock = newLibraryRepositoryMock();
|
libraryMock = newLibraryRepositoryMock();
|
||||||
moveMock = newMoveRepositoryMock();
|
|
||||||
personMock = newPersonRepositoryMock();
|
|
||||||
storageMock = newStorageRepositoryMock();
|
storageMock = newStorageRepositoryMock();
|
||||||
userMock = newUserRepositoryMock();
|
userMock = newUserRepositoryMock();
|
||||||
|
|
||||||
sut = new UserService(
|
sut = new UserService(albumMock, assetMock, cryptoRepositoryMock, jobMock, libraryMock, storageMock, userMock);
|
||||||
albumMock,
|
|
||||||
assetMock,
|
|
||||||
cryptoRepositoryMock,
|
|
||||||
jobMock,
|
|
||||||
libraryMock,
|
|
||||||
moveMock,
|
|
||||||
personMock,
|
|
||||||
storageMock,
|
|
||||||
userMock,
|
|
||||||
);
|
|
||||||
|
|
||||||
when(userMock.get).calledWith(adminUser.id).mockResolvedValue(adminUser);
|
when(userMock.get).calledWith(adminUser.id).mockResolvedValue(adminUser);
|
||||||
when(userMock.get).calledWith(adminUser.id, undefined).mockResolvedValue(adminUser);
|
when(userMock.get).calledWith(adminUser.id, undefined).mockResolvedValue(adminUser);
|
||||||
|
@ -10,8 +10,6 @@ import {
|
|||||||
ICryptoRepository,
|
ICryptoRepository,
|
||||||
IJobRepository,
|
IJobRepository,
|
||||||
ILibraryRepository,
|
ILibraryRepository,
|
||||||
IMoveRepository,
|
|
||||||
IPersonRepository,
|
|
||||||
IStorageRepository,
|
IStorageRepository,
|
||||||
IUserRepository,
|
IUserRepository,
|
||||||
} from '../repositories';
|
} from '../repositories';
|
||||||
@ -30,7 +28,6 @@ import { UserCore } from './user.core';
|
|||||||
@Injectable()
|
@Injectable()
|
||||||
export class UserService {
|
export class UserService {
|
||||||
private logger = new Logger(UserService.name);
|
private logger = new Logger(UserService.name);
|
||||||
private storageCore: StorageCore;
|
|
||||||
private userCore: UserCore;
|
private userCore: UserCore;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@ -39,12 +36,9 @@ export class UserService {
|
|||||||
@Inject(ICryptoRepository) cryptoRepository: ICryptoRepository,
|
@Inject(ICryptoRepository) cryptoRepository: ICryptoRepository,
|
||||||
@Inject(IJobRepository) private jobRepository: IJobRepository,
|
@Inject(IJobRepository) private jobRepository: IJobRepository,
|
||||||
@Inject(ILibraryRepository) libraryRepository: ILibraryRepository,
|
@Inject(ILibraryRepository) libraryRepository: ILibraryRepository,
|
||||||
@Inject(IMoveRepository) moveRepository: IMoveRepository,
|
|
||||||
@Inject(IPersonRepository) personRepository: IPersonRepository,
|
|
||||||
@Inject(IStorageRepository) private storageRepository: IStorageRepository,
|
@Inject(IStorageRepository) private storageRepository: IStorageRepository,
|
||||||
@Inject(IUserRepository) private userRepository: IUserRepository,
|
@Inject(IUserRepository) private userRepository: IUserRepository,
|
||||||
) {
|
) {
|
||||||
this.storageCore = new StorageCore(storageRepository, assetRepository, moveRepository, personRepository);
|
|
||||||
this.userCore = UserCore.create(cryptoRepository, libraryRepository, userRepository);
|
this.userCore = UserCore.create(cryptoRepository, libraryRepository, userRepository);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -171,11 +165,11 @@ export class UserService {
|
|||||||
this.logger.log(`Deleting user: ${user.id}`);
|
this.logger.log(`Deleting user: ${user.id}`);
|
||||||
|
|
||||||
const folders = [
|
const folders = [
|
||||||
this.storageCore.getLibraryFolder(user),
|
StorageCore.getLibraryFolder(user),
|
||||||
this.storageCore.getFolderLocation(StorageFolder.UPLOAD, user.id),
|
StorageCore.getFolderLocation(StorageFolder.UPLOAD, user.id),
|
||||||
this.storageCore.getFolderLocation(StorageFolder.PROFILE, user.id),
|
StorageCore.getFolderLocation(StorageFolder.PROFILE, user.id),
|
||||||
this.storageCore.getFolderLocation(StorageFolder.THUMBNAILS, user.id),
|
StorageCore.getFolderLocation(StorageFolder.THUMBNAILS, user.id),
|
||||||
this.storageCore.getFolderLocation(StorageFolder.ENCODED_VIDEO, user.id),
|
StorageCore.getFolderLocation(StorageFolder.ENCODED_VIDEO, user.id),
|
||||||
];
|
];
|
||||||
|
|
||||||
for (const folder of folders) {
|
for (const folder of folders) {
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
import { IStorageRepository } from '@app/domain';
|
import { IStorageRepository, StorageCore } from '@app/domain';
|
||||||
|
|
||||||
|
export const newStorageRepositoryMock = (reset = true): jest.Mocked<IStorageRepository> => {
|
||||||
|
if (reset) {
|
||||||
|
StorageCore.reset();
|
||||||
|
}
|
||||||
|
|
||||||
export const newStorageRepositoryMock = (): jest.Mocked<IStorageRepository> => {
|
|
||||||
return {
|
return {
|
||||||
createZipStream: jest.fn(),
|
createZipStream: jest.fn(),
|
||||||
createReadStream: jest.fn(),
|
createReadStream: jest.fn(),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user