You've already forked pigallery2
							
							
				mirror of
				https://github.com/bpatrik/pigallery2.git
				synced 2025-10-30 23:57:43 +02:00 
			
		
		
		
	Removing memory DB. fixes #572
This commit is contained in:
		| @@ -1,7 +1,7 @@ | ||||
| import {Config} from '../src/common/config/private/Config'; | ||||
| import {ObjectManagers} from '../src/backend/model/ObjectManagers'; | ||||
| import {DiskMangerWorker} from '../src/backend/model/threading/DiskMangerWorker'; | ||||
| import {IndexingManager} from '../src/backend/model/database/sql/IndexingManager'; | ||||
| import {IndexingManager} from '../src/backend/model/database/IndexingManager'; | ||||
| import * as path from 'path'; | ||||
| import * as fs from 'fs'; | ||||
| import {Utils} from '../src/common/Utils'; | ||||
| @@ -13,8 +13,8 @@ import {IJob} from '../src/backend/model/jobs/jobs/IJob'; | ||||
| import {JobProgressStates} from '../src/common/entities/job/JobProgressDTO'; | ||||
| import {JobProgress} from '../src/backend/model/jobs/jobs/JobProgress'; | ||||
| import {ContentWrapper} from '../src/common/entities/ConentWrapper'; | ||||
| import {GalleryManager} from '../src/backend/model/database/sql/GalleryManager'; | ||||
| import {PersonManager} from '../src/backend/model/database/sql/PersonManager'; | ||||
| import {GalleryManager} from '../src/backend/model/database/GalleryManager'; | ||||
| import {PersonManager} from '../src/backend/model/database/PersonManager'; | ||||
| import {GalleryRouter} from '../src/backend/routes/GalleryRouter'; | ||||
| import {Express} from 'express'; | ||||
| import {PersonRouter} from '../src/backend/routes/PersonRouter'; | ||||
|   | ||||
| @@ -5,7 +5,7 @@ import { | ||||
|   PersonDTO, | ||||
| } from '../../common/entities/PersonDTO'; | ||||
| import { Utils } from '../../common/Utils'; | ||||
| import {PersonEntry} from '../model/database/sql/enitites/PersonEntry'; | ||||
| import {PersonEntry} from '../model/database/enitites/PersonEntry'; | ||||
|  | ||||
| export class PersonMWs { | ||||
|   public static async updatePerson( | ||||
|   | ||||
| @@ -1,10 +1,6 @@ | ||||
| import { NextFunction, Request, Response } from 'express'; | ||||
| import { ErrorCodes, ErrorDTO } from '../../../common/entities/Error'; | ||||
| import { ObjectManagers } from '../../model/ObjectManagers'; | ||||
| import { Config } from '../../../common/config/private/Config'; | ||||
| import { ISQLGalleryManager } from '../../model/database/sql/IGalleryManager'; | ||||
| import { DatabaseType } from '../../../common/config/private/PrivateConfig'; | ||||
| import { ISQLPersonManager } from '../../model/database/sql/IPersonManager'; | ||||
| import { StatisticDTO } from '../../../common/entities/settings/StatisticDTO'; | ||||
|  | ||||
| export class AdminMWs { | ||||
| @@ -13,19 +9,11 @@ export class AdminMWs { | ||||
|     res: Response, | ||||
|     next: NextFunction | ||||
|   ): Promise<void> { | ||||
|     if (Config.Database.type === DatabaseType.memory) { | ||||
|       return next( | ||||
|         new ErrorDTO( | ||||
|           ErrorCodes.GENERAL_ERROR, | ||||
|           'Statistic is only available for indexed content' | ||||
|         ) | ||||
|       ); | ||||
|     } | ||||
|  | ||||
|     const galleryManager = ObjectManagers.getInstance() | ||||
|       .GalleryManager as ISQLGalleryManager; | ||||
|       .GalleryManager; | ||||
|     const personManager = ObjectManagers.getInstance() | ||||
|       .PersonManager as ISQLPersonManager; | ||||
|       .PersonManager; | ||||
|     try { | ||||
|       req.resultPipe = { | ||||
|         directories: await galleryManager.countDirectories(), | ||||
| @@ -60,19 +48,10 @@ export class AdminMWs { | ||||
|     res: Response, | ||||
|     next: NextFunction | ||||
|   ): Promise<void> { | ||||
|     if (Config.Database.type === DatabaseType.memory) { | ||||
|       return next( | ||||
|         new ErrorDTO( | ||||
|           ErrorCodes.GENERAL_ERROR, | ||||
|           'Statistic is only available for indexed content' | ||||
|         ) | ||||
|       ); | ||||
|     } | ||||
|  | ||||
|     const galleryManager = ObjectManagers.getInstance() | ||||
|       .GalleryManager as ISQLGalleryManager; | ||||
|     try { | ||||
|       req.resultPipe = await galleryManager.getPossibleDuplicates(); | ||||
|       req.resultPipe = await ObjectManagers.getInstance() | ||||
|         .GalleryManager.getPossibleDuplicates(); | ||||
|       return next(); | ||||
|     } catch (err) { | ||||
|       if (err instanceof Error) { | ||||
|   | ||||
| @@ -14,7 +14,7 @@ import {ThumbnailSourceType} from '../../model/threading/PhotoWorker'; | ||||
| import {MediaDTO} from '../../../common/entities/MediaDTO'; | ||||
| import {PhotoProcessing} from '../../model/fileprocessing/PhotoProcessing'; | ||||
| import {ServerTime} from '../ServerTimingMWs'; | ||||
| import {PersonEntry} from '../../model/database/sql/enitites/PersonEntry'; | ||||
| import {PersonEntry} from '../../model/database/enitites/PersonEntry'; | ||||
|  | ||||
| export class ThumbnailGeneratorMWs { | ||||
|   private static ThumbnailMapEntries = | ||||
|   | ||||
| @@ -1,20 +1,19 @@ | ||||
| /* eslint-disable @typescript-eslint/no-var-requires */ | ||||
| import { IUserManager } from './database/interfaces/IUserManager'; | ||||
| import { IGalleryManager } from './database/interfaces/IGalleryManager'; | ||||
| import { ISearchManager } from './database/interfaces/ISearchManager'; | ||||
| import { SQLConnection } from './database/sql/SQLConnection'; | ||||
| import { ISharingManager } from './database/interfaces/ISharingManager'; | ||||
| import {SQLConnection} from './database/SQLConnection'; | ||||
| import {Logger} from '../Logger'; | ||||
| import { IIndexingManager } from './database/interfaces/IIndexingManager'; | ||||
| import { IPersonManager } from './database/interfaces/IPersonManager'; | ||||
| import { IVersionManager } from './database/interfaces/IVersionManager'; | ||||
| import { IJobManager } from './database/interfaces/IJobManager'; | ||||
| import {LocationManager} from './database/LocationManager'; | ||||
| import { IAlbumManager } from './database/interfaces/IAlbumManager'; | ||||
| import {JobManager} from './jobs/JobManager'; | ||||
| import { IPreviewManager } from './database/interfaces/IPreviewManager'; | ||||
| import {ParentDirectoryDTO} from '../../common/entities/DirectoryDTO'; | ||||
| import { IObjectManager } from './database/interfaces/IObjectManager'; | ||||
| import {GalleryManager} from './database/GalleryManager'; | ||||
| import {UserManager} from './database/UserManager'; | ||||
| import {IndexingManager} from './database/IndexingManager'; | ||||
| import {SearchManager} from './database/SearchManager'; | ||||
| import {VersionManager} from './database/VersionManager'; | ||||
| import {PreviewManager} from './database/PreviewManager'; | ||||
| import {AlbumManager} from './database/AlbumManager'; | ||||
| import {PersonManager} from './database/PersonManager'; | ||||
| import {SharingManager} from './database/SharingManager'; | ||||
| import {IObjectManager} from './database/IObjectManager'; | ||||
|  | ||||
| const LOG_TAG = '[ObjectManagers]'; | ||||
|  | ||||
| @@ -22,27 +21,27 @@ export class ObjectManagers { | ||||
|   private static instance: ObjectManagers = null; | ||||
|  | ||||
|   private readonly managers: IObjectManager[]; | ||||
|   private galleryManager: IGalleryManager; | ||||
|   private userManager: IUserManager; | ||||
|   private searchManager: ISearchManager; | ||||
|   private sharingManager: ISharingManager; | ||||
|   private indexingManager: IIndexingManager; | ||||
|   private personManager: IPersonManager; | ||||
|   private previewManager: IPreviewManager; | ||||
|   private versionManager: IVersionManager; | ||||
|   private jobManager: IJobManager; | ||||
|   private galleryManager: GalleryManager; | ||||
|   private userManager: UserManager; | ||||
|   private searchManager: SearchManager; | ||||
|   private sharingManager: SharingManager; | ||||
|   private indexingManager: IndexingManager; | ||||
|   private personManager: PersonManager; | ||||
|   private previewManager: PreviewManager; | ||||
|   private versionManager: VersionManager; | ||||
|   private jobManager: JobManager; | ||||
|   private locationManager: LocationManager; | ||||
|   private albumManager: IAlbumManager; | ||||
|   private albumManager: AlbumManager; | ||||
|  | ||||
|   constructor() { | ||||
|     this.managers = []; | ||||
|   } | ||||
|  | ||||
|   get VersionManager(): IVersionManager { | ||||
|   get VersionManager(): VersionManager { | ||||
|     return this.versionManager; | ||||
|   } | ||||
|  | ||||
|   set VersionManager(value: IVersionManager) { | ||||
|   set VersionManager(value: VersionManager) { | ||||
|     if (this.versionManager) { | ||||
|       this.managers.splice(this.managers.indexOf(this.versionManager), 1); | ||||
|     } | ||||
| @@ -62,11 +61,11 @@ export class ObjectManagers { | ||||
|     this.managers.push(this.locationManager); | ||||
|   } | ||||
|  | ||||
|   get AlbumManager(): IAlbumManager { | ||||
|   get AlbumManager(): AlbumManager { | ||||
|     return this.albumManager; | ||||
|   } | ||||
|  | ||||
|   set AlbumManager(value: IAlbumManager) { | ||||
|   set AlbumManager(value: AlbumManager) { | ||||
|     if (this.albumManager) { | ||||
|       this.managers.splice(this.managers.indexOf(this.albumManager), 1); | ||||
|     } | ||||
| @@ -74,11 +73,11 @@ export class ObjectManagers { | ||||
|     this.managers.push(this.albumManager); | ||||
|   } | ||||
|  | ||||
|   get PersonManager(): IPersonManager { | ||||
|   get PersonManager(): PersonManager { | ||||
|     return this.personManager; | ||||
|   } | ||||
|  | ||||
|   set PersonManager(value: IPersonManager) { | ||||
|   set PersonManager(value: PersonManager) { | ||||
|     if (this.personManager) { | ||||
|       this.managers.splice(this.managers.indexOf(this.personManager), 1); | ||||
|     } | ||||
| @@ -86,11 +85,11 @@ export class ObjectManagers { | ||||
|     this.managers.push(this.personManager); | ||||
|   } | ||||
|  | ||||
|   get PreviewManager(): IPreviewManager { | ||||
|   get PreviewManager(): PreviewManager { | ||||
|     return this.previewManager; | ||||
|   } | ||||
|  | ||||
|   set PreviewManager(value: IPreviewManager) { | ||||
|   set PreviewManager(value: PreviewManager) { | ||||
|     if (this.previewManager) { | ||||
|       this.managers.splice(this.managers.indexOf(this.previewManager), 1); | ||||
|     } | ||||
| @@ -98,76 +97,76 @@ export class ObjectManagers { | ||||
|     this.managers.push(this.previewManager); | ||||
|   } | ||||
|  | ||||
|   get IndexingManager(): IIndexingManager { | ||||
|   get IndexingManager(): IndexingManager { | ||||
|     return this.indexingManager; | ||||
|   } | ||||
|  | ||||
|   set IndexingManager(value: IIndexingManager) { | ||||
|   set IndexingManager(value: IndexingManager) { | ||||
|     if (this.indexingManager) { | ||||
|       this.managers.splice(this.managers.indexOf(this.indexingManager), 1); | ||||
|       this.managers.splice(this.managers.indexOf(this.indexingManager as IObjectManager), 1); | ||||
|     } | ||||
|     this.indexingManager = value; | ||||
|     this.managers.push(this.indexingManager); | ||||
|     this.managers.push(this.indexingManager as IObjectManager); | ||||
|   } | ||||
|  | ||||
|   get GalleryManager(): IGalleryManager { | ||||
|   get GalleryManager(): GalleryManager { | ||||
|     return this.galleryManager; | ||||
|   } | ||||
|  | ||||
|   set GalleryManager(value: IGalleryManager) { | ||||
|   set GalleryManager(value: GalleryManager) { | ||||
|     if (this.galleryManager) { | ||||
|       this.managers.splice(this.managers.indexOf(this.galleryManager), 1); | ||||
|       this.managers.splice(this.managers.indexOf(this.galleryManager as IObjectManager), 1); | ||||
|     } | ||||
|     this.galleryManager = value; | ||||
|     this.managers.push(this.galleryManager); | ||||
|     this.managers.push(this.galleryManager as IObjectManager); | ||||
|   } | ||||
|  | ||||
|   get UserManager(): IUserManager { | ||||
|   get UserManager(): UserManager { | ||||
|     return this.userManager; | ||||
|   } | ||||
|  | ||||
|   set UserManager(value: IUserManager) { | ||||
|   set UserManager(value: UserManager) { | ||||
|     if (this.userManager) { | ||||
|       this.managers.splice(this.managers.indexOf(this.userManager), 1); | ||||
|       this.managers.splice(this.managers.indexOf(this.userManager as IObjectManager), 1); | ||||
|     } | ||||
|     this.userManager = value; | ||||
|     this.managers.push(this.userManager); | ||||
|     this.managers.push(this.userManager as IObjectManager); | ||||
|   } | ||||
|  | ||||
|   get SearchManager(): ISearchManager { | ||||
|   get SearchManager(): SearchManager { | ||||
|     return this.searchManager; | ||||
|   } | ||||
|  | ||||
|   set SearchManager(value: ISearchManager) { | ||||
|   set SearchManager(value: SearchManager) { | ||||
|     if (this.searchManager) { | ||||
|       this.managers.splice(this.managers.indexOf(this.searchManager), 1); | ||||
|       this.managers.splice(this.managers.indexOf(this.searchManager as IObjectManager), 1); | ||||
|     } | ||||
|     this.searchManager = value; | ||||
|     this.managers.push(this.searchManager); | ||||
|     this.managers.push(this.searchManager as IObjectManager); | ||||
|   } | ||||
|  | ||||
|   get SharingManager(): ISharingManager { | ||||
|   get SharingManager(): SharingManager { | ||||
|     return this.sharingManager; | ||||
|   } | ||||
|  | ||||
|   set SharingManager(value: ISharingManager) { | ||||
|   set SharingManager(value: SharingManager) { | ||||
|     if (this.sharingManager) { | ||||
|       this.managers.splice(this.managers.indexOf(this.sharingManager), 1); | ||||
|       this.managers.splice(this.managers.indexOf(this.sharingManager as IObjectManager), 1); | ||||
|     } | ||||
|     this.sharingManager = value; | ||||
|     this.managers.push(this.sharingManager); | ||||
|     this.managers.push(this.sharingManager as IObjectManager); | ||||
|   } | ||||
|  | ||||
|   get JobManager(): IJobManager { | ||||
|   get JobManager(): JobManager { | ||||
|     return this.jobManager; | ||||
|   } | ||||
|  | ||||
|   set JobManager(value: IJobManager) { | ||||
|   set JobManager(value: JobManager) { | ||||
|     if (this.jobManager) { | ||||
|       this.managers.splice(this.managers.indexOf(this.jobManager), 1); | ||||
|       this.managers.splice(this.managers.indexOf(this.jobManager as IObjectManager), 1); | ||||
|     } | ||||
|     this.jobManager = value; | ||||
|     this.managers.push(this.jobManager); | ||||
|     this.managers.push(this.jobManager as IObjectManager); | ||||
|   } | ||||
|  | ||||
|   public static getInstance(): ObjectManagers { | ||||
| @@ -193,38 +192,23 @@ export class ObjectManagers { | ||||
|     Logger.debug(LOG_TAG, 'Object manager reset'); | ||||
|   } | ||||
|  | ||||
|   public static async InitMemoryManagers(): Promise<void> { | ||||
|     await ObjectManagers.reset(); | ||||
|     this.initManagers('memory'); | ||||
|     Logger.debug(LOG_TAG, 'Memory DB inited'); | ||||
|   } | ||||
|  | ||||
|   public static async InitSQLManagers(): Promise<void> { | ||||
|     await ObjectManagers.reset(); | ||||
|     await SQLConnection.init(); | ||||
|     this.initManagers('sql'); | ||||
|     this.initManagers(); | ||||
|     Logger.debug(LOG_TAG, 'SQL DB inited'); | ||||
|   } | ||||
|  | ||||
|   private static initManagers(type: 'memory' | 'sql'): void { | ||||
|     ObjectManagers.getInstance().AlbumManager = | ||||
|       new (require(`./database/${type}/AlbumManager`).AlbumManager)(); | ||||
|     ObjectManagers.getInstance().GalleryManager = | ||||
|       new (require(`./database/${type}/GalleryManager`).GalleryManager)(); | ||||
|     ObjectManagers.getInstance().IndexingManager = | ||||
|       new (require(`./database/${type}/IndexingManager`).IndexingManager)(); | ||||
|     ObjectManagers.getInstance().PersonManager = | ||||
|       new (require(`./database/${type}/PersonManager`).PersonManager)(); | ||||
|     ObjectManagers.getInstance().PreviewManager = | ||||
|       new (require(`./database/${type}/PreviewManager`).PreviewManager)(); | ||||
|     ObjectManagers.getInstance().SearchManager = | ||||
|       new (require(`./database/${type}/SearchManager`).SearchManager)(); | ||||
|     ObjectManagers.getInstance().SharingManager = | ||||
|       new (require(`./database/${type}/SharingManager`).SharingManager)(); | ||||
|     ObjectManagers.getInstance().UserManager = | ||||
|       new (require(`./database/${type}/UserManager`).UserManager)(); | ||||
|     ObjectManagers.getInstance().VersionManager = | ||||
|       new (require(`./database/${type}/VersionManager`).VersionManager)(); | ||||
|   private static initManagers(): void { | ||||
|     ObjectManagers.getInstance().AlbumManager = new AlbumManager(); | ||||
|     ObjectManagers.getInstance().GalleryManager = new GalleryManager(); | ||||
|     ObjectManagers.getInstance().IndexingManager = new IndexingManager(); | ||||
|     ObjectManagers.getInstance().PersonManager = new PersonManager(); | ||||
|     ObjectManagers.getInstance().PreviewManager = new PreviewManager(); | ||||
|     ObjectManagers.getInstance().SearchManager = new SearchManager(); | ||||
|     ObjectManagers.getInstance().SharingManager = new SharingManager(); | ||||
|     ObjectManagers.getInstance().UserManager = new UserManager(); | ||||
|     ObjectManagers.getInstance().VersionManager = new VersionManager(); | ||||
|     ObjectManagers.getInstance().JobManager = new JobManager(); | ||||
|     ObjectManagers.getInstance().LocationManager = new LocationManager(); | ||||
|   } | ||||
| @@ -232,7 +216,7 @@ export class ObjectManagers { | ||||
|   public async onDataChange( | ||||
|     changedDir: ParentDirectoryDTO = null | ||||
|   ): Promise<void> { | ||||
|     await this.VersionManager.onNewDataVersion(changedDir); | ||||
|     await this.VersionManager.onNewDataVersion(); | ||||
|  | ||||
|     for (const manager of this.managers) { | ||||
|       if (manager === this.versionManager) { | ||||
|   | ||||
| @@ -1,17 +1,16 @@ | ||||
| import {SQLConnection} from './SQLConnection'; | ||||
| import {AlbumBaseEntity} from './enitites/album/AlbumBaseEntity'; | ||||
| import { AlbumBaseDTO } from '../../../../common/entities/album/AlbumBaseDTO'; | ||||
| import { SavedSearchDTO } from '../../../../common/entities/album/SavedSearchDTO'; | ||||
| import { ObjectManagers } from '../../ObjectManagers'; | ||||
| import { ISQLSearchManager } from './ISearchManager'; | ||||
| import { SearchQueryDTO } from '../../../../common/entities/SearchQueryDTO'; | ||||
| import {AlbumBaseDTO} from '../../../common/entities/album/AlbumBaseDTO'; | ||||
| import {SavedSearchDTO} from '../../../common/entities/album/SavedSearchDTO'; | ||||
| import {ObjectManagers} from '../ObjectManagers'; | ||||
| import {SearchQueryDTO} from '../../../common/entities/SearchQueryDTO'; | ||||
| import {SavedSearchEntity} from './enitites/album/SavedSearchEntity'; | ||||
| import { IAlbumManager } from '../interfaces/IAlbumManager'; | ||||
| import { Logger } from '../../../Logger'; | ||||
| import {Logger} from '../../Logger'; | ||||
| import {IObjectManager} from './IObjectManager'; | ||||
| 
 | ||||
| const LOG_TAG = '[AlbumManager]'; | ||||
| 
 | ||||
| export class AlbumManager implements IAlbumManager { | ||||
| export class AlbumManager implements IObjectManager { | ||||
|   /** | ||||
|    * Person table contains denormalized data that needs to update when isDBValid = false | ||||
|    */ | ||||
| @@ -21,9 +20,8 @@ export class AlbumManager implements IAlbumManager { | ||||
|     const connection = await SQLConnection.getConnection(); | ||||
|     const preview = | ||||
|       await ObjectManagers.getInstance().PreviewManager.getAlbumPreview(album); | ||||
|     const count = await ( | ||||
|       ObjectManagers.getInstance().SearchManager as ISQLSearchManager | ||||
|     ).getCount((album as SavedSearchDTO).searchQuery); | ||||
|     const count = await | ||||
|       ObjectManagers.getInstance().SearchManager.getCount((album as SavedSearchDTO).searchQuery); | ||||
| 
 | ||||
|     await connection | ||||
|       .createQueryBuilder() | ||||
| @@ -1,28 +1,24 @@ | ||||
| import {IGalleryManager} from '../interfaces/IGalleryManager'; | ||||
| import { | ||||
|   ParentDirectoryDTO, | ||||
|   SubDirectoryDTO, | ||||
| } from '../../../../common/entities/DirectoryDTO'; | ||||
| import {ParentDirectoryDTO, SubDirectoryDTO,} from '../../../common/entities/DirectoryDTO'; | ||||
| import * as path from 'path'; | ||||
| import * as fs from 'fs'; | ||||
| import {DirectoryEntity} from './enitites/DirectoryEntity'; | ||||
| import {SQLConnection} from './SQLConnection'; | ||||
| import {PhotoEntity} from './enitites/PhotoEntity'; | ||||
| import {ProjectPath} from '../../../ProjectPath'; | ||||
| import {Config} from '../../../../common/config/private/Config'; | ||||
| import {ISQLGalleryManager} from './IGalleryManager'; | ||||
| import {ProjectPath} from '../../ProjectPath'; | ||||
| import {Config} from '../../../common/config/private/Config'; | ||||
| import {Connection} from 'typeorm'; | ||||
| import {MediaEntity} from './enitites/MediaEntity'; | ||||
| import {VideoEntity} from './enitites/VideoEntity'; | ||||
| import {DiskMangerWorker} from '../../threading/DiskMangerWorker'; | ||||
| import {Logger} from '../../../Logger'; | ||||
| import {ObjectManagers} from '../../ObjectManagers'; | ||||
| import {DuplicatesDTO} from '../../../../common/entities/DuplicatesDTO'; | ||||
| import {ReIndexingSensitivity} from '../../../../common/config/private/PrivateConfig'; | ||||
| import {DiskMangerWorker} from '../threading/DiskMangerWorker'; | ||||
| import {Logger} from '../../Logger'; | ||||
| import {ObjectManagers} from '../ObjectManagers'; | ||||
| import {DuplicatesDTO} from '../../../common/entities/DuplicatesDTO'; | ||||
| import {ReIndexingSensitivity} from '../../../common/config/private/PrivateConfig'; | ||||
| import {IObjectManager} from './IObjectManager'; | ||||
| 
 | ||||
| const LOG_TAG = '[GalleryManager]'; | ||||
| 
 | ||||
| export class GalleryManager implements IGalleryManager, ISQLGalleryManager { | ||||
| export class GalleryManager  { | ||||
|   public static parseRelativeDirePath(relativeDirectoryName: string): { | ||||
|     name: string; | ||||
|     parent: string; | ||||
| @@ -1,4 +1,4 @@ | ||||
| import { ParentDirectoryDTO } from '../../../../common/entities/DirectoryDTO'; | ||||
| import { ParentDirectoryDTO } from '../../../common/entities/DirectoryDTO'; | ||||
| 
 | ||||
| export interface IObjectManager { | ||||
|   onNewDataVersion?: (changedDir?: ParentDirectoryDTO) => Promise<void>; | ||||
| @@ -1,38 +1,31 @@ | ||||
| import {DirectoryDTOUtils, DirectoryPathDTO, ParentDirectoryDTO} from '../../../../common/entities/DirectoryDTO'; | ||||
| import {DirectoryDTOUtils, DirectoryPathDTO, ParentDirectoryDTO} from '../../../common/entities/DirectoryDTO'; | ||||
| import {DirectoryEntity} from './enitites/DirectoryEntity'; | ||||
| import {SQLConnection} from './SQLConnection'; | ||||
| import {DiskManager} from '../../DiskManger'; | ||||
| import {DiskManager} from '../DiskManger'; | ||||
| import {PhotoEntity, PhotoMetadataEntity} from './enitites/PhotoEntity'; | ||||
| import {Utils} from '../../../../common/Utils'; | ||||
| import { | ||||
|   FaceRegion, | ||||
|   PhotoMetadata, | ||||
| } from '../../../../common/entities/PhotoDTO'; | ||||
| import {Utils} from '../../../common/Utils'; | ||||
| import {PhotoMetadata,} from '../../../common/entities/PhotoDTO'; | ||||
| import {Connection, Repository} from 'typeorm'; | ||||
| import {MediaEntity} from './enitites/MediaEntity'; | ||||
| import {MediaDTO, MediaDTOUtils} from '../../../../common/entities/MediaDTO'; | ||||
| import {MediaDTO, MediaDTOUtils} from '../../../common/entities/MediaDTO'; | ||||
| import {VideoEntity} from './enitites/VideoEntity'; | ||||
| import {FileEntity} from './enitites/FileEntity'; | ||||
| import {FileDTO} from '../../../../common/entities/FileDTO'; | ||||
| import {NotificationManager} from '../../NotifocationManager'; | ||||
| import {ObjectManagers} from '../../ObjectManagers'; | ||||
| import {IIndexingManager} from '../interfaces/IIndexingManager'; | ||||
| import {DiskMangerWorker} from '../../threading/DiskMangerWorker'; | ||||
| import {Logger} from '../../../Logger'; | ||||
| import { | ||||
|   ServerPG2ConfMap, | ||||
|   ServerSidePG2ConfAction, | ||||
| } from '../../../../common/PG2ConfMap'; | ||||
| import {ProjectPath} from '../../../ProjectPath'; | ||||
| import {FileDTO} from '../../../common/entities/FileDTO'; | ||||
| import {NotificationManager} from '../NotifocationManager'; | ||||
| import {ObjectManagers} from '../ObjectManagers'; | ||||
| import {DiskMangerWorker} from '../threading/DiskMangerWorker'; | ||||
| import {Logger} from '../../Logger'; | ||||
| import {ServerPG2ConfMap, ServerSidePG2ConfAction,} from '../../../common/PG2ConfMap'; | ||||
| import {ProjectPath} from '../../ProjectPath'; | ||||
| import * as path from 'path'; | ||||
| import * as fs from 'fs'; | ||||
| import {SearchQueryDTO} from '../../../../common/entities/SearchQueryDTO'; | ||||
| import {SearchQueryDTO} from '../../../common/entities/SearchQueryDTO'; | ||||
| import {PersonEntry} from './enitites/PersonEntry'; | ||||
| import {PersonJunctionTable} from './enitites/PersonJunctionTable'; | ||||
| 
 | ||||
| const LOG_TAG = '[IndexingManager]'; | ||||
| 
 | ||||
| export class IndexingManager implements IIndexingManager { | ||||
| export class IndexingManager { | ||||
|   SavingReady: Promise<void> = null; | ||||
|   private SavingReadyPR: () => void = null; | ||||
|   private savingQueue: ParentDirectoryDTO[] = []; | ||||
| @@ -2,7 +2,7 @@ import { GPSMetadata } from '../../../common/entities/PhotoDTO'; | ||||
| import * as NodeGeocoder from 'node-geocoder'; | ||||
| import { LocationLookupException } from '../../exceptions/LocationLookupException'; | ||||
| import { LRU } from '../../../common/Utils'; | ||||
| import { IObjectManager } from './interfaces/IObjectManager'; | ||||
| import { IObjectManager } from './IObjectManager'; | ||||
| import { ParentDirectoryDTO } from '../../../common/entities/DirectoryDTO'; | ||||
|  | ||||
| export class LocationManager implements IObjectManager { | ||||
|   | ||||
| @@ -1,15 +1,14 @@ | ||||
| import {SQLConnection} from './SQLConnection'; | ||||
| import {PersonEntry} from './enitites/PersonEntry'; | ||||
| import {PersonDTO} from '../../../../common/entities/PersonDTO'; | ||||
| import {ISQLPersonManager} from './IPersonManager'; | ||||
| import {Logger} from '../../../Logger'; | ||||
| import {FaceRegion} from '../../../../common/entities/PhotoDTO'; | ||||
| import {PersonDTO} from '../../../common/entities/PersonDTO'; | ||||
| import {Logger} from '../../Logger'; | ||||
| import {SQL_COLLATE} from './enitites/EntityUtils'; | ||||
| import {PersonJunctionTable} from './enitites/PersonJunctionTable'; | ||||
| import {IObjectManager} from './IObjectManager'; | ||||
| 
 | ||||
| const LOG_TAG = '[PersonManager]'; | ||||
| 
 | ||||
| export class PersonManager implements ISQLPersonManager { | ||||
| export class PersonManager  implements IObjectManager{ | ||||
|   persons: PersonEntry[] = null; | ||||
|   /** | ||||
|    * Person table contains denormalized data that needs to update when isDBValid = false | ||||
| @@ -1,29 +1,27 @@ | ||||
| import { Config } from '../../../../common/config/private/Config'; | ||||
| import {Config} from '../../../common/config/private/Config'; | ||||
| import {Brackets, SelectQueryBuilder, WhereExpression} from 'typeorm'; | ||||
| import {MediaEntity} from './enitites/MediaEntity'; | ||||
| import { DiskMangerWorker } from '../../threading/DiskMangerWorker'; | ||||
| import { ObjectManagers } from '../../ObjectManagers'; | ||||
| import { DatabaseType } from '../../../../common/config/private/PrivateConfig'; | ||||
| import { SortingMethods } from '../../../../common/entities/SortingMethods'; | ||||
| import { ISQLSearchManager } from './ISearchManager'; | ||||
| import { | ||||
|   IPreviewManager, | ||||
|   PreviewPhotoDTOWithID, | ||||
| } from '../interfaces/IPreviewManager'; | ||||
| import {DiskMangerWorker} from '../threading/DiskMangerWorker'; | ||||
| import {ObjectManagers} from '../ObjectManagers'; | ||||
| import {DatabaseType} from '../../../common/config/private/PrivateConfig'; | ||||
| import {SortingMethods} from '../../../common/entities/SortingMethods'; | ||||
| import {SQLConnection} from './SQLConnection'; | ||||
| import { | ||||
|   SearchQueryDTO, | ||||
|   SearchQueryTypes, | ||||
|   TextSearch, | ||||
| } from '../../../../common/entities/SearchQueryDTO'; | ||||
| import {SearchQueryDTO, SearchQueryTypes, TextSearch,} from '../../../common/entities/SearchQueryDTO'; | ||||
| import {DirectoryEntity} from './enitites/DirectoryEntity'; | ||||
| import { ParentDirectoryDTO } from '../../../../common/entities/DirectoryDTO'; | ||||
| import {ParentDirectoryDTO} from '../../../common/entities/DirectoryDTO'; | ||||
| import * as path from 'path'; | ||||
| import { Utils } from '../../../../common/Utils'; | ||||
| import {Utils} from '../../../common/Utils'; | ||||
| import {PreviewPhotoDTO} from '../../../common/entities/PhotoDTO'; | ||||
| import {IObjectManager} from './IObjectManager'; | ||||
| 
 | ||||
| const LOG_TAG = '[PreviewManager]'; | ||||
| 
 | ||||
| export class PreviewManager implements IPreviewManager { | ||||
| // ID is need within the backend so it can be saved to DB (ID is the external key)
 | ||||
| export interface PreviewPhotoDTOWithID extends PreviewPhotoDTO { | ||||
|   id: number; | ||||
| } | ||||
| 
 | ||||
| export class PreviewManager implements IObjectManager { | ||||
|   private static DIRECTORY_SELECT = ['directory.name', 'directory.path']; | ||||
| 
 | ||||
|   private static setSorting<T>( | ||||
| @@ -109,9 +107,8 @@ export class PreviewManager implements IPreviewManager { | ||||
|   public async getAlbumPreview(album: { | ||||
|     searchQuery: SearchQueryDTO; | ||||
|   }): Promise<PreviewPhotoDTOWithID> { | ||||
|     const albumQuery: Brackets = await ( | ||||
|       ObjectManagers.getInstance().SearchManager as ISQLSearchManager | ||||
|     ).prepareAndBuildWhereQuery(album.searchQuery); | ||||
|     const albumQuery: Brackets = await | ||||
|       ObjectManagers.getInstance().SearchManager.prepareAndBuildWhereQuery(album.searchQuery); | ||||
|     const connection = await SQLConnection.getConnection(); | ||||
| 
 | ||||
|     const previewQuery = (): SelectQueryBuilder<MediaEntity> => { | ||||
| @@ -133,9 +130,8 @@ export class PreviewManager implements IPreviewManager { | ||||
|         text: '', | ||||
|       } as TextSearch) | ||||
|     ) { | ||||
|       const previewFilterQuery = await ( | ||||
|         ObjectManagers.getInstance().SearchManager as ISQLSearchManager | ||||
|       ).prepareAndBuildWhereQuery(Config.Preview.SearchQuery); | ||||
|       const previewFilterQuery = await | ||||
|         ObjectManagers.getInstance().SearchManager.prepareAndBuildWhereQuery(Config.Preview.SearchQuery); | ||||
|       previewMedia = await previewQuery() | ||||
|         .andWhere(previewFilterQuery) | ||||
|         .limit(1) | ||||
| @@ -178,7 +174,7 @@ export class PreviewManager implements IPreviewManager { | ||||
|               dir: dir.id, | ||||
|             }); | ||||
|             if (Config.Database.type === DatabaseType.mysql) { | ||||
|               q.orWhere("directory.path like :path || '%'", { | ||||
|               q.orWhere('directory.path like :path || \'%\'', { | ||||
|                 path: DiskMangerWorker.pathFromParent(dir), | ||||
|               }); | ||||
|             } else { | ||||
| @@ -209,9 +205,7 @@ export class PreviewManager implements IPreviewManager { | ||||
|     ) { | ||||
|       previewMedia = await previewQuery() | ||||
|         .andWhere( | ||||
|           await ( | ||||
|             ObjectManagers.getInstance().SearchManager as ISQLSearchManager | ||||
|           ).prepareAndBuildWhereQuery(Config.Preview.SearchQuery) | ||||
|           await ObjectManagers.getInstance().SearchManager.prepareAndBuildWhereQuery(Config.Preview.SearchQuery) | ||||
|         ) | ||||
|         .limit(1) | ||||
|         .getOne(); | ||||
| @@ -1,35 +1,26 @@ | ||||
| import 'reflect-metadata'; | ||||
| import { | ||||
|   Connection, | ||||
|   createConnection, | ||||
|   DataSourceOptions, | ||||
|   getConnection, | ||||
| } from 'typeorm'; | ||||
| import {Connection, createConnection, DataSourceOptions, getConnection,} from 'typeorm'; | ||||
| import {UserEntity} from './enitites/UserEntity'; | ||||
| import { UserRoles } from '../../../../common/entities/UserDTO'; | ||||
| import {UserRoles} from '../../../common/entities/UserDTO'; | ||||
| import {PhotoEntity} from './enitites/PhotoEntity'; | ||||
| import {DirectoryEntity} from './enitites/DirectoryEntity'; | ||||
| import { Config } from '../../../../common/config/private/Config'; | ||||
| import {Config} from '../../../common/config/private/Config'; | ||||
| import {SharingEntity} from './enitites/SharingEntity'; | ||||
| import { PasswordHelper } from '../../PasswordHelper'; | ||||
| import { ProjectPath } from '../../../ProjectPath'; | ||||
| import {PasswordHelper} from '../PasswordHelper'; | ||||
| import {ProjectPath} from '../../ProjectPath'; | ||||
| import {VersionEntity} from './enitites/VersionEntity'; | ||||
| import { Logger } from '../../../Logger'; | ||||
| import {Logger} from '../../Logger'; | ||||
| import {MediaEntity} from './enitites/MediaEntity'; | ||||
| import {VideoEntity} from './enitites/VideoEntity'; | ||||
| import { DataStructureVersion } from '../../../../common/DataStructureVersion'; | ||||
| import {DataStructureVersion} from '../../../common/DataStructureVersion'; | ||||
| import {FileEntity} from './enitites/FileEntity'; | ||||
| import {PersonEntry} from './enitites/PersonEntry'; | ||||
| import { Utils } from '../../../../common/Utils'; | ||||
| import {Utils} from '../../../common/Utils'; | ||||
| import * as path from 'path'; | ||||
| import { | ||||
|   DatabaseType, | ||||
|   ServerDataBaseConfig, | ||||
|   SQLLogLevel, | ||||
| } from '../../../../common/config/private/PrivateConfig'; | ||||
| import {DatabaseType, ServerDataBaseConfig, SQLLogLevel,} from '../../../common/config/private/PrivateConfig'; | ||||
| import {AlbumBaseEntity} from './enitites/album/AlbumBaseEntity'; | ||||
| import {SavedSearchEntity} from './enitites/album/SavedSearchEntity'; | ||||
| import { NotificationManager } from '../../NotifocationManager'; | ||||
| import {NotificationManager} from '../NotifocationManager'; | ||||
| import {PersonJunctionTable} from './enitites/PersonJunctionTable'; | ||||
| 
 | ||||
| const LOG_TAG = '[SQLConnection]'; | ||||
| @@ -78,7 +69,8 @@ export class SQLConnection { | ||||
|     try { | ||||
|       await getConnection('test').close(); | ||||
|       // eslint-disable-next-line no-empty
 | ||||
|     } catch (err) {} | ||||
|     } catch (err) { | ||||
|     } | ||||
|     const options: any = this.getDriver(config); | ||||
|     options.name = 'test'; | ||||
|     options.entities = [ | ||||
| @@ -191,7 +183,7 @@ export class SQLConnection { | ||||
|     try { | ||||
|       return await createConnection(options); | ||||
|     } catch (e) { | ||||
|       if (e.sqlMessage === "Unknown database '" + options.database + "'") { | ||||
|       if (e.sqlMessage === 'Unknown database \'' + options.database + '\'') { | ||||
|         Logger.debug(LOG_TAG, 'creating database: ' + options.database); | ||||
|         const tmpOption = Utils.clone(options); | ||||
|         // eslint-disable-next-line @typescript-eslint/ban-ts-comment
 | ||||
| @@ -213,7 +205,8 @@ export class SQLConnection { | ||||
|     try { | ||||
|       version = (await connection.getRepository(VersionEntity).find())[0]; | ||||
|       // eslint-disable-next-line no-empty
 | ||||
|     } catch (ex) {} | ||||
|     } catch (ex) { | ||||
|     } | ||||
|     if (version && version.version === DataStructureVersion) { | ||||
|       return; | ||||
|     } | ||||
| @@ -230,7 +223,8 @@ export class SQLConnection { | ||||
|         .createQueryBuilder('user') | ||||
|         .getMany(); | ||||
|       // eslint-disable-next-line no-empty
 | ||||
|     } catch (ex) {} | ||||
|     } catch (ex) { | ||||
|     } | ||||
|     await connection.dropDatabase(); | ||||
|     await connection.synchronize(); | ||||
|     await connection.getRepository(VersionEntity).save(version); | ||||
| @@ -1,13 +1,13 @@ | ||||
| /* eslint-disable no-case-declarations */ | ||||
| import {AutoCompleteItem} from '../../../../common/entities/AutoCompleteItem'; | ||||
| import {SearchResultDTO} from '../../../../common/entities/SearchResultDTO'; | ||||
| import {AutoCompleteItem} from '../../../common/entities/AutoCompleteItem'; | ||||
| import {SearchResultDTO} from '../../../common/entities/SearchResultDTO'; | ||||
| import {SQLConnection} from './SQLConnection'; | ||||
| import {PhotoEntity} from './enitites/PhotoEntity'; | ||||
| import {DirectoryEntity} from './enitites/DirectoryEntity'; | ||||
| import {MediaEntity} from './enitites/MediaEntity'; | ||||
| import {PersonEntry} from './enitites/PersonEntry'; | ||||
| import {Brackets, SelectQueryBuilder, WhereExpression} from 'typeorm'; | ||||
| import {Config} from '../../../../common/config/private/Config'; | ||||
| import {Config} from '../../../common/config/private/Config'; | ||||
| import { | ||||
|   ANDSearchQuery, | ||||
|   DistanceSearch, | ||||
| @@ -25,18 +25,16 @@ import { | ||||
|   TextSearch, | ||||
|   TextSearchQueryMatchTypes, | ||||
|   ToDateSearch, | ||||
| } from '../../../../common/entities/SearchQueryDTO'; | ||||
| } from '../../../common/entities/SearchQueryDTO'; | ||||
| import {GalleryManager} from './GalleryManager'; | ||||
| import {ObjectManagers} from '../../ObjectManagers'; | ||||
| import {PhotoDTO} from '../../../../common/entities/PhotoDTO'; | ||||
| import {DatabaseType} from '../../../../common/config/private/PrivateConfig'; | ||||
| import {ISQLGalleryManager} from './IGalleryManager'; | ||||
| import {ISQLSearchManager} from './ISearchManager'; | ||||
| import {Utils} from '../../../../common/Utils'; | ||||
| import {ObjectManagers} from '../ObjectManagers'; | ||||
| import {PhotoDTO} from '../../../common/entities/PhotoDTO'; | ||||
| import {DatabaseType} from '../../../common/config/private/PrivateConfig'; | ||||
| import {Utils} from '../../../common/Utils'; | ||||
| import {FileEntity} from './enitites/FileEntity'; | ||||
| import {SQL_COLLATE} from './enitites/EntityUtils'; | ||||
| 
 | ||||
| export class SearchManager implements ISQLSearchManager { | ||||
| export class SearchManager { | ||||
|   private DIRECTORY_SELECT = [ | ||||
|     'directory.id', | ||||
|     'directory.name', | ||||
| @@ -333,9 +331,7 @@ export class SearchManager implements ISQLSearchManager { | ||||
|         // setting previews
 | ||||
|         if (result.directories) { | ||||
|           for (const item of result.directories) { | ||||
|             await ( | ||||
|               ObjectManagers.getInstance().GalleryManager as ISQLGalleryManager | ||||
|             ).fillPreviewForSubDir(connection, item as DirectoryEntity); | ||||
|             await ObjectManagers.getInstance().GalleryManager.fillPreviewForSubDir(connection, item as DirectoryEntity); | ||||
|           } | ||||
|         } | ||||
|         if ( | ||||
| @@ -1,12 +1,11 @@ | ||||
| import { ISharingManager } from '../interfaces/ISharingManager'; | ||||
| import { SharingDTO } from '../../../../common/entities/SharingDTO'; | ||||
| import {SharingDTO} from '../../../common/entities/SharingDTO'; | ||||
| import {SQLConnection} from './SQLConnection'; | ||||
| import {SharingEntity} from './enitites/SharingEntity'; | ||||
| import { Config } from '../../../../common/config/private/Config'; | ||||
| import { PasswordHelper } from '../../PasswordHelper'; | ||||
| import {Config} from '../../../common/config/private/Config'; | ||||
| import {PasswordHelper} from '../PasswordHelper'; | ||||
| import {DeleteResult, FindOptionsWhere} from 'typeorm'; | ||||
| 
 | ||||
| export class SharingManager implements ISharingManager { | ||||
| export class SharingManager { | ||||
|   private static async removeExpiredLink(): Promise<DeleteResult> { | ||||
|     const connection = await SQLConnection.getConnection(); | ||||
|     return await connection | ||||
| @@ -66,7 +65,7 @@ export class SharingManager implements ISharingManager { | ||||
|       sharing.timeStamp < Date.now() - Config.Sharing.updateTimeout && | ||||
|       forceUpdate !== true | ||||
|     ) { | ||||
|       throw new Error("Sharing is locked, can't update anymore"); | ||||
|       throw new Error('Sharing is locked, can\'t update anymore'); | ||||
|     } | ||||
|     if (inSharing.password == null) { | ||||
|       sharing.password = null; | ||||
| @@ -1,11 +1,10 @@ | ||||
| import {UserDTO, UserRoles} from '../../../../common/entities/UserDTO'; | ||||
| import {IUserManager} from '../interfaces/IUserManager'; | ||||
| import {UserDTO, UserRoles} from '../../../common/entities/UserDTO'; | ||||
| import {UserEntity} from './enitites/UserEntity'; | ||||
| import {SQLConnection} from './SQLConnection'; | ||||
| import {PasswordHelper} from '../../PasswordHelper'; | ||||
| import {PasswordHelper} from '../PasswordHelper'; | ||||
| import {FindOptionsWhere} from 'typeorm'; | ||||
| 
 | ||||
| export class UserManager implements IUserManager { | ||||
| export class UserManager { | ||||
| 
 | ||||
| 
 | ||||
|   public async findOne(filter: FindOptionsWhere<UserEntity>): Promise<UserEntity> { | ||||
| @@ -1,11 +1,11 @@ | ||||
| import * as crypto from 'crypto'; | ||||
| import { IVersionManager } from '../interfaces/IVersionManager'; | ||||
| import { DataStructureVersion } from '../../../../common/DataStructureVersion'; | ||||
| import {DataStructureVersion} from '../../../common/DataStructureVersion'; | ||||
| import {SQLConnection} from './SQLConnection'; | ||||
| import {DirectoryEntity} from './enitites/DirectoryEntity'; | ||||
| import {MediaEntity} from './enitites/MediaEntity'; | ||||
| import {IObjectManager} from './IObjectManager'; | ||||
| 
 | ||||
| export class VersionManager implements IVersionManager { | ||||
| export class VersionManager implements IObjectManager { | ||||
|   private allMediaCount = 0; | ||||
|   private latestDirectoryStatus: { | ||||
|     name: string; | ||||
| @@ -10,11 +10,11 @@ import { | ||||
| import { | ||||
|   ParentDirectoryDTO, | ||||
|   SubDirectoryDTO, | ||||
| } from '../../../../../common/entities/DirectoryDTO'; | ||||
| } from '../../../../common/entities/DirectoryDTO'; | ||||
| import { MediaEntity } from './MediaEntity'; | ||||
| import { FileEntity } from './FileEntity'; | ||||
| import { columnCharsetCS } from './EntityUtils'; | ||||
| import { MediaDTO } from '../../../../../common/entities/MediaDTO'; | ||||
| import { MediaDTO } from '../../../../common/entities/MediaDTO'; | ||||
| 
 | ||||
| @Entity() | ||||
| @Unique(['name', 'path']) | ||||
| @@ -1,6 +1,6 @@ | ||||
| import { Config } from '../../../../../common/config/private/Config'; | ||||
| import { Config } from '../../../../common/config/private/Config'; | ||||
| import { ColumnOptions } from 'typeorm/decorator/options/ColumnOptions'; | ||||
| import { DatabaseType } from '../../../../../common/config/private/PrivateConfig'; | ||||
| import { DatabaseType } from '../../../../common/config/private/PrivateConfig'; | ||||
| 
 | ||||
| export class ColumnCharsetCS implements ColumnOptions { | ||||
|   public get charset(): string { | ||||
| @@ -6,7 +6,7 @@ import { | ||||
|   PrimaryGeneratedColumn, | ||||
| } from 'typeorm'; | ||||
| import { DirectoryEntity } from './DirectoryEntity'; | ||||
| import { FileDTO } from '../../../../../common/entities/FileDTO'; | ||||
| import { FileDTO } from '../../../../common/entities/FileDTO'; | ||||
| import { columnCharsetCS } from './EntityUtils'; | ||||
| 
 | ||||
| @Entity() | ||||
| @@ -13,14 +13,14 @@ import { | ||||
|   MediaDimension, | ||||
|   MediaDTO, | ||||
|   MediaMetadata, | ||||
| } from '../../../../../common/entities/MediaDTO'; | ||||
| } from '../../../../common/entities/MediaDTO'; | ||||
| import { PersonJunctionTable} from './PersonJunctionTable'; | ||||
| import { columnCharsetCS } from './EntityUtils'; | ||||
| import { | ||||
|   CameraMetadata, FaceRegion, | ||||
|   GPSMetadata, | ||||
|   PositionMetaData, | ||||
| } from '../../../../../common/entities/PhotoDTO'; | ||||
| } from '../../../../common/entities/PhotoDTO'; | ||||
| 
 | ||||
| export class MediaDimensionEntity implements MediaDimension { | ||||
|   @Column('int') | ||||
| @@ -9,7 +9,7 @@ import { | ||||
| } from 'typeorm'; | ||||
| import {PersonJunctionTable} from './PersonJunctionTable'; | ||||
| import {columnCharsetCS} from './EntityUtils'; | ||||
| import { PersonDTO } from '../../../../../common/entities/PersonDTO'; | ||||
| import { PersonDTO } from '../../../../common/entities/PersonDTO'; | ||||
| 
 | ||||
| @Entity() | ||||
| @Unique(['name']) | ||||
| @@ -2,7 +2,7 @@ import { ChildEntity, Column } from 'typeorm'; | ||||
| import { | ||||
|   PhotoDTO, | ||||
|   PhotoMetadata, | ||||
| } from '../../../../../common/entities/PhotoDTO'; | ||||
| } from '../../../../common/entities/PhotoDTO'; | ||||
| import { MediaEntity, MediaMetadataEntity } from './MediaEntity'; | ||||
| 
 | ||||
| export class PhotoMetadataEntity | ||||
| @@ -1,7 +1,7 @@ | ||||
| import { Column, Entity, ManyToOne, PrimaryGeneratedColumn } from 'typeorm'; | ||||
| import { SharingDTO } from '../../../../../common/entities/SharingDTO'; | ||||
| import { SharingDTO } from '../../../../common/entities/SharingDTO'; | ||||
| import { UserEntity } from './UserEntity'; | ||||
| import { UserDTO } from '../../../../../common/entities/UserDTO'; | ||||
| import { UserDTO } from '../../../../common/entities/UserDTO'; | ||||
| 
 | ||||
| @Entity() | ||||
| export class SharingEntity implements SharingDTO { | ||||
| @@ -1,4 +1,4 @@ | ||||
| import { UserDTO, UserRoles } from '../../../../../common/entities/UserDTO'; | ||||
| import {UserDTO, UserRoles} from '../../../../common/entities/UserDTO'; | ||||
| import {Column, Entity, PrimaryGeneratedColumn, Unique} from 'typeorm'; | ||||
| 
 | ||||
| @Entity() | ||||
| @@ -3,7 +3,7 @@ import { MediaEntity, MediaMetadataEntity } from './MediaEntity'; | ||||
| import { | ||||
|   VideoDTO, | ||||
|   VideoMetadata, | ||||
| } from '../../../../../common/entities/VideoDTO'; | ||||
| } from '../../../../common/entities/VideoDTO'; | ||||
| 
 | ||||
| export class VideoMetadataEntity | ||||
|   extends MediaMetadataEntity | ||||
							
								
								
									
										28
									
								
								src/backend/model/database/enitites/album/AlbumBaseEntity.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								src/backend/model/database/enitites/album/AlbumBaseEntity.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | ||||
| import {Column, Entity, Index, ManyToOne, PrimaryGeneratedColumn, TableInheritance,} from 'typeorm'; | ||||
| import {MediaEntity} from '../MediaEntity'; | ||||
| import {columnCharsetCS} from '../EntityUtils'; | ||||
| import {AlbumBaseDTO} from '../../../../../common/entities/album/AlbumBaseDTO'; | ||||
|  | ||||
| @Entity() | ||||
| @TableInheritance({column: {type: 'varchar', name: 'type', length: 24}}) | ||||
| export class AlbumBaseEntity implements AlbumBaseDTO { | ||||
|   @Index() | ||||
|   @PrimaryGeneratedColumn({unsigned: true}) | ||||
|   id: number; | ||||
|  | ||||
|   @Index() | ||||
|   @Column(columnCharsetCS) | ||||
|   name: string; | ||||
|  | ||||
|   /** | ||||
|    * Locked albums are not possible to remove | ||||
|    */ | ||||
|   @Column({default: false}) | ||||
|   locked: boolean; | ||||
|  | ||||
|   @Column('int', {unsigned: true, default: 0}) | ||||
|   count: number; | ||||
|  | ||||
|   @ManyToOne((type) => MediaEntity, {onDelete: 'SET NULL', nullable: true}) | ||||
|   public preview: MediaEntity; | ||||
| } | ||||
| @@ -1,7 +1,7 @@ | ||||
| import { ChildEntity, Column } from 'typeorm'; | ||||
| import { AlbumBaseEntity } from './AlbumBaseEntity'; | ||||
| import { SavedSearchDTO } from '../../../../../../common/entities/album/SavedSearchDTO'; | ||||
| import { SearchQueryDTO } from '../../../../../../common/entities/SearchQueryDTO'; | ||||
| import { SavedSearchDTO } from '../../../../../common/entities/album/SavedSearchDTO'; | ||||
| import { SearchQueryDTO } from '../../../../../common/entities/SearchQueryDTO'; | ||||
| 
 | ||||
| @ChildEntity() | ||||
| export class SavedSearchEntity | ||||
| @@ -1,41 +0,0 @@ | ||||
| import { SearchQueryDTO } from '../../../../common/entities/SearchQueryDTO'; | ||||
| import { AlbumBaseDTO } from '../../../../common/entities/album/AlbumBaseDTO'; | ||||
| import { IObjectManager } from './IObjectManager'; | ||||
|  | ||||
| export interface IAlbumManager extends IObjectManager { | ||||
|   /** | ||||
|    * Creates a saved search type of album | ||||
|    */ | ||||
|   addSavedSearch( | ||||
|     name: string, | ||||
|     searchQuery: SearchQueryDTO, | ||||
|     lockedAlbum?: boolean | ||||
|   ): Promise<void>; | ||||
|  | ||||
|   /** | ||||
|    * Creates a saved search type of album if the album is not yet exists | ||||
|    * lockAlbum: Album cannot be removed from the UI | ||||
|    */ | ||||
|   addIfNotExistSavedSearch( | ||||
|     name: string, | ||||
|     searchQuery: SearchQueryDTO, | ||||
|     lockedAlbum?: boolean | ||||
|   ): Promise<void>; | ||||
|  | ||||
|   /** | ||||
|    * Deletes an album | ||||
|    */ | ||||
|   deleteAlbum(id: number): Promise<void>; | ||||
|  | ||||
|   /** | ||||
|    * Returns with all albums | ||||
|    */ | ||||
|   getAlbums(): Promise<AlbumBaseDTO[]>; | ||||
|  | ||||
|   /** | ||||
|    * Updates previews and album counts | ||||
|    */ | ||||
|   onNewDataVersion(): Promise<void>; | ||||
|  | ||||
|   resetPreviews(): Promise<void>; | ||||
| } | ||||
| @@ -1,10 +0,0 @@ | ||||
| import { ParentDirectoryDTO } from '../../../../common/entities/DirectoryDTO'; | ||||
| import { IObjectManager } from './IObjectManager'; | ||||
|  | ||||
| export interface IGalleryManager extends IObjectManager { | ||||
|   listDirectory( | ||||
|     relativeDirectoryName: string, | ||||
|     knownLastModified?: number, | ||||
|     knownLastScanned?: number | ||||
|   ): Promise<ParentDirectoryDTO>; | ||||
| } | ||||
| @@ -1,13 +0,0 @@ | ||||
| import { ParentDirectoryDTO } from '../../../../common/entities/DirectoryDTO'; | ||||
| import { IObjectManager } from './IObjectManager'; | ||||
|  | ||||
| export interface IIndexingManager extends IObjectManager { | ||||
|   SavingReady: Promise<void>; | ||||
|   IsSavingInProgress: boolean; | ||||
|  | ||||
|   indexDirectory(relativeDirectoryName: string): Promise<ParentDirectoryDTO>; | ||||
|  | ||||
|   resetDB(): Promise<void>; | ||||
|  | ||||
|   saveToDB(scannedDirectory: ParentDirectoryDTO): Promise<void>; | ||||
| } | ||||
| @@ -1,22 +0,0 @@ | ||||
| import { JobProgressDTO } from '../../../../common/entities/job/JobProgressDTO'; | ||||
| import { JobDTO } from '../../../../common/entities/job/JobDTO'; | ||||
| import { IObjectManager } from './IObjectManager'; | ||||
|  | ||||
| export interface IJobManager extends IObjectManager { | ||||
|   run( | ||||
|     jobId: string, | ||||
|     config: unknown, | ||||
|     soloRun: boolean, | ||||
|     allowParallelRun: boolean | ||||
|   ): Promise<void>; | ||||
|  | ||||
|   stop(jobId: string): void; | ||||
|  | ||||
|   getProgresses(): { [key: string]: JobProgressDTO }; | ||||
|  | ||||
|   getAvailableJobs(): JobDTO[]; | ||||
|  | ||||
|   stopSchedules(): void; | ||||
|  | ||||
|   runSchedules(): void; | ||||
| } | ||||
| @@ -1,16 +0,0 @@ | ||||
| import {PersonEntry} from '../sql/enitites/PersonEntry'; | ||||
| import {PersonDTO} from '../../../../common/entities/PersonDTO'; | ||||
| import {IObjectManager} from './IObjectManager'; | ||||
|  | ||||
| export interface IPersonManager extends IObjectManager { | ||||
|   getAll(): Promise<PersonEntry[]>; | ||||
|  | ||||
|   get(name: string): Promise<PersonEntry>; | ||||
|  | ||||
|   // saving a Person with a sample region. Person entry cannot exist without a face region | ||||
|   saveAll(person: { name: string; mediaId: number }[]): Promise<void>; | ||||
|  | ||||
|   updatePerson(name: string, partialPerson: PersonDTO): Promise<PersonEntry>; | ||||
|  | ||||
|   resetPreviews(): Promise<void>; | ||||
| } | ||||
| @@ -1,26 +0,0 @@ | ||||
| import { PreviewPhotoDTO } from '../../../../common/entities/PhotoDTO'; | ||||
| import { IObjectManager } from './IObjectManager'; | ||||
| import { SearchQueryDTO } from '../../../../common/entities/SearchQueryDTO'; | ||||
|  | ||||
| export interface IPreviewManager extends IObjectManager { | ||||
|   setAndGetPreviewForDirectory(dir: { | ||||
|     id: number; | ||||
|     name: string; | ||||
|     path: string; | ||||
|   }): Promise<PreviewPhotoDTOWithID>; | ||||
|  | ||||
|   getAlbumPreview(album: { | ||||
|     searchQuery: SearchQueryDTO; | ||||
|   }): Promise<PreviewPhotoDTOWithID>; | ||||
|  | ||||
|   getPartialDirsWithoutPreviews(): Promise< | ||||
|     { id: number; name: string; path: string }[] | ||||
|   >; | ||||
|  | ||||
|   resetPreviews(): Promise<void>; | ||||
| } | ||||
|  | ||||
| // ID is need within the backend so it can be saved to DB (ID is the external key) | ||||
| export interface PreviewPhotoDTOWithID extends PreviewPhotoDTO { | ||||
|   id: number; | ||||
| } | ||||
| @@ -1,19 +0,0 @@ | ||||
| import { AutoCompleteItem } from '../../../../common/entities/AutoCompleteItem'; | ||||
| import { SearchResultDTO } from '../../../../common/entities/SearchResultDTO'; | ||||
| import { | ||||
|   SearchQueryDTO, | ||||
|   SearchQueryTypes, | ||||
| } from '../../../../common/entities/SearchQueryDTO'; | ||||
| import { PhotoDTO } from '../../../../common/entities/PhotoDTO'; | ||||
| import { IObjectManager } from './IObjectManager'; | ||||
|  | ||||
| export interface ISearchManager extends IObjectManager { | ||||
|   autocomplete( | ||||
|     text: string, | ||||
|     type: SearchQueryTypes | ||||
|   ): Promise<AutoCompleteItem[]>; | ||||
|  | ||||
|   search(query: SearchQueryDTO): Promise<SearchResultDTO>; | ||||
|  | ||||
|   getRandomPhoto(queryFilter: SearchQueryDTO): Promise<PhotoDTO>; | ||||
| } | ||||
| @@ -1,15 +0,0 @@ | ||||
| import { SharingDTO } from '../../../../common/entities/SharingDTO'; | ||||
| import { IObjectManager } from './IObjectManager'; | ||||
| import { FindOptionsWhere } from 'typeorm'; | ||||
|  | ||||
| export interface ISharingManager extends IObjectManager { | ||||
|   findOne(filter: FindOptionsWhere<SharingDTO>): Promise<SharingDTO>; | ||||
|  | ||||
|   createSharing(sharing: SharingDTO): Promise<SharingDTO>; | ||||
|  | ||||
|   updateSharing(sharing: SharingDTO, forceUpdate: boolean): Promise<SharingDTO>; | ||||
|  | ||||
|   listAll(): Promise<SharingDTO[]>; | ||||
|  | ||||
|   deleteSharing(sharingKey: string): Promise<void>; | ||||
| } | ||||
| @@ -1,16 +0,0 @@ | ||||
| import { UserDTO, UserRoles } from '../../../../common/entities/UserDTO'; | ||||
| import { IObjectManager } from './IObjectManager'; | ||||
| import { FindOptionsWhere } from 'typeorm'; | ||||
|  | ||||
| export interface IUserManager extends IObjectManager { | ||||
|   findOne(filter: FindOptionsWhere<UserDTO>): Promise<UserDTO>; | ||||
|  | ||||
|   find(filter: FindOptionsWhere<UserDTO>): Promise<UserDTO[]>; | ||||
|  | ||||
|   createUser(user: UserDTO): Promise<UserDTO>; | ||||
|  | ||||
|   deleteUser(id: number): Promise<UserDTO>; | ||||
|  | ||||
|   changeRole(id: number, newRole: UserRoles): Promise<UserDTO>; | ||||
|  | ||||
| } | ||||
| @@ -1,5 +0,0 @@ | ||||
| import { IObjectManager } from './IObjectManager'; | ||||
|  | ||||
| export interface IVersionManager extends IObjectManager { | ||||
|   getDataVersion(): Promise<string>; | ||||
| } | ||||
| @@ -1,28 +0,0 @@ | ||||
| import {AlbumBaseDTO} from '../../../../common/entities/album/AlbumBaseDTO'; | ||||
| import {IAlbumManager} from '../interfaces/IAlbumManager'; | ||||
|  | ||||
| export class AlbumManager implements IAlbumManager { | ||||
|   resetPreviews(): Promise<void> { | ||||
|     throw new Error('not supported by memory DB'); | ||||
|   } | ||||
|  | ||||
|   onNewDataVersion(): Promise<void> { | ||||
|     throw new Error('not supported by memory DB'); | ||||
|   } | ||||
|  | ||||
|   public async addIfNotExistSavedSearch(): Promise<void> { | ||||
|     throw new Error('not supported by memory DB'); | ||||
|   } | ||||
|  | ||||
|   public async addSavedSearch(): Promise<void> { | ||||
|     throw new Error('not supported by memory DB'); | ||||
|   } | ||||
|  | ||||
|   public async deleteAlbum(): Promise<void> { | ||||
|     throw new Error('not supported by memory DB'); | ||||
|   } | ||||
|  | ||||
|   public async getAlbums(): Promise<AlbumBaseDTO[]> { | ||||
|     throw new Error('not supported by memory DB'); | ||||
|   } | ||||
| } | ||||
| @@ -1,39 +0,0 @@ | ||||
| import {DirectoryDTOUtils, ParentDirectoryDTO} from '../../../../common/entities/DirectoryDTO'; | ||||
| import {IGalleryManager} from '../interfaces/IGalleryManager'; | ||||
| import * as path from 'path'; | ||||
| import * as fs from 'fs'; | ||||
| import {DiskManager} from '../../DiskManger'; | ||||
| import {ProjectPath} from '../../../ProjectPath'; | ||||
| import {Config} from '../../../../common/config/private/Config'; | ||||
| import {DiskMangerWorker} from '../../threading/DiskMangerWorker'; | ||||
| import {ReIndexingSensitivity} from '../../../../common/config/private/PrivateConfig'; | ||||
| import {ServerPG2ConfMap} from '../../../../common/PG2ConfMap'; | ||||
|  | ||||
| export class GalleryManager implements IGalleryManager { | ||||
|   public async listDirectory( | ||||
|     relativeDirectoryName: string, | ||||
|     knownLastModified?: number, | ||||
|     knownLastScanned?: number | ||||
|   ): Promise<ParentDirectoryDTO> { | ||||
|     // If it seems that the content did not change, do not work on it | ||||
|     if (knownLastModified && knownLastScanned) { | ||||
|       const stat = fs.statSync( | ||||
|         path.join(ProjectPath.ImageFolder, relativeDirectoryName) | ||||
|       ); | ||||
|       const lastModified = DiskMangerWorker.calcLastModified(stat); | ||||
|       if ( | ||||
|         Date.now() - knownLastScanned <= | ||||
|         Config.Indexing.cachedFolderTimeout && | ||||
|         lastModified === knownLastModified && | ||||
|         Config.Indexing.reIndexingSensitivity < | ||||
|         ReIndexingSensitivity.high | ||||
|       ) { | ||||
|         return Promise.resolve(null); | ||||
|       } | ||||
|     } | ||||
|     const dir = await DiskManager.scanDirectory(relativeDirectoryName); | ||||
|     DirectoryDTOUtils.addReferences(dir); | ||||
|     dir.metaFile = dir.metaFile.filter((m) => !ServerPG2ConfMap[m.name]); | ||||
|     return dir; | ||||
|   } | ||||
| } | ||||
| @@ -1,19 +0,0 @@ | ||||
| import { IIndexingManager } from '../interfaces/IIndexingManager'; | ||||
| import { ParentDirectoryDTO } from '../../../../common/entities/DirectoryDTO'; | ||||
|  | ||||
| export class IndexingManager implements IIndexingManager { | ||||
|   IsSavingInProgress: boolean; | ||||
|   SavingReady: Promise<void>; | ||||
|  | ||||
|   saveToDB(scannedDirectory: ParentDirectoryDTO): Promise<void> { | ||||
|     throw new Error('not supported by memory DB'); | ||||
|   } | ||||
|  | ||||
|   indexDirectory(relativeDirectoryName: string): Promise<ParentDirectoryDTO> { | ||||
|     throw new Error('not supported by memory DB'); | ||||
|   } | ||||
|  | ||||
|   resetDB(): Promise<void> { | ||||
|     throw new Error('not supported by memory DB'); | ||||
|   } | ||||
| } | ||||
| @@ -1,29 +0,0 @@ | ||||
| import { IPersonManager } from '../interfaces/IPersonManager'; | ||||
| import { PersonDTO } from '../../../../common/entities/PersonDTO'; | ||||
| import { FaceRegion } from '../../../../common/entities/PhotoDTO'; | ||||
|  | ||||
| export class PersonManager implements IPersonManager { | ||||
|   resetPreviews(): Promise<void> { | ||||
|     throw new Error('not supported by memory DB'); | ||||
|   } | ||||
|  | ||||
|   saveAll(person: { name: string; mediaId: number }[]): Promise<void> { | ||||
|     throw new Error('not supported by memory DB'); | ||||
|   } | ||||
|  | ||||
|   getAll(): Promise<any[]> { | ||||
|     throw new Error('not supported by memory DB'); | ||||
|   } | ||||
|  | ||||
|   get(name: string): Promise<any> { | ||||
|     throw new Error('not supported by memory DB'); | ||||
|   } | ||||
|  | ||||
|   onGalleryIndexUpdate(): Promise<void> { | ||||
|     throw new Error('not supported by memory DB'); | ||||
|   } | ||||
|  | ||||
|   updatePerson(name: string, partialPerson: PersonDTO): Promise<any> { | ||||
|     throw new Error('not supported by memory DB'); | ||||
|   } | ||||
| } | ||||
| @@ -1,24 +0,0 @@ | ||||
| import { IPreviewManager } from '../interfaces/IPreviewManager'; | ||||
| import { DirectoryPathDTO } from '../../../../common/entities/DirectoryDTO'; | ||||
| import { MediaDTO } from '../../../../common/entities/MediaDTO'; | ||||
| import { SavedSearchDTO } from '../../../../common/entities/album/SavedSearchDTO'; | ||||
|  | ||||
| export class PreviewManager implements IPreviewManager { | ||||
|   resetPreviews(): Promise<void> { | ||||
|     throw new Error('not implemented'); | ||||
|   } | ||||
|  | ||||
|   getPartialDirsWithoutPreviews(): Promise< | ||||
|     { id: number; name: string; path: string }[] | ||||
|   > { | ||||
|     throw new Error('not implemented'); | ||||
|   } | ||||
|  | ||||
|   getAlbumPreview(album: SavedSearchDTO): Promise<MediaDTO> { | ||||
|     throw new Error('not implemented'); | ||||
|   } | ||||
|  | ||||
|   setAndGetPreviewForDirectory(dir: DirectoryPathDTO): Promise<MediaDTO> { | ||||
|     throw new Error('not implemented'); | ||||
|   } | ||||
| } | ||||
| @@ -1,25 +0,0 @@ | ||||
| import { AutoCompleteItem } from '../../../../common/entities/AutoCompleteItem'; | ||||
| import { ISearchManager } from '../interfaces/ISearchManager'; | ||||
| import { SearchResultDTO } from '../../../../common/entities/SearchResultDTO'; | ||||
| import { | ||||
|   SearchQueryDTO, | ||||
|   SearchQueryTypes, | ||||
| } from '../../../../common/entities/SearchQueryDTO'; | ||||
| import { PhotoDTO } from '../../../../common/entities/PhotoDTO'; | ||||
|  | ||||
| export class SearchManager implements ISearchManager { | ||||
|   getRandomPhoto(queryFilter: SearchQueryDTO): Promise<PhotoDTO> { | ||||
|     throw new Error('Method not implemented.'); | ||||
|   } | ||||
|  | ||||
|   autocomplete( | ||||
|     text: string, | ||||
|     type: SearchQueryTypes | ||||
|   ): Promise<AutoCompleteItem[]> { | ||||
|     throw new Error('Method not implemented.'); | ||||
|   } | ||||
|  | ||||
|   search(query: SearchQueryDTO): Promise<SearchResultDTO> { | ||||
|     throw new Error('Method not implemented.'); | ||||
|   } | ||||
| } | ||||
| @@ -1,27 +0,0 @@ | ||||
| import { ISharingManager } from '../interfaces/ISharingManager'; | ||||
| import { SharingDTO } from '../../../../common/entities/SharingDTO'; | ||||
|  | ||||
| export class SharingManager implements ISharingManager { | ||||
|   deleteSharing(sharingKey: string): Promise<void> { | ||||
|     throw new Error('not implemented'); | ||||
|   } | ||||
|  | ||||
|   listAll(): Promise<SharingDTO[]> { | ||||
|     throw new Error('not implemented'); | ||||
|   } | ||||
|  | ||||
|   findOne(filter: any): Promise<SharingDTO> { | ||||
|     throw new Error('not implemented'); | ||||
|   } | ||||
|  | ||||
|   createSharing(sharing: SharingDTO): Promise<SharingDTO> { | ||||
|     throw new Error('not implemented'); | ||||
|   } | ||||
|  | ||||
|   updateSharing( | ||||
|     sharing: SharingDTO, | ||||
|     forceUpdate: boolean | ||||
|   ): Promise<SharingDTO> { | ||||
|     throw new Error('not implemented'); | ||||
|   } | ||||
| } | ||||
| @@ -1,97 +0,0 @@ | ||||
| import { UserDTO, UserRoles } from '../../../../common/entities/UserDTO'; | ||||
| import { IUserManager } from '../interfaces/IUserManager'; | ||||
| import { ProjectPath } from '../../../ProjectPath'; | ||||
| import { Utils } from '../../../../common/Utils'; | ||||
| import * as fs from 'fs'; | ||||
| import * as path from 'path'; | ||||
| import { PasswordHelper } from '../../PasswordHelper'; | ||||
|  | ||||
| export class UserManager implements IUserManager { | ||||
|   private db: { users?: UserDTO[]; idCounter?: number } = {}; | ||||
|   private readonly dbPath: string; | ||||
|  | ||||
|   constructor() { | ||||
|     this.dbPath = path.join(ProjectPath.DBFolder, 'users.db'); | ||||
|     if (fs.existsSync(this.dbPath)) { | ||||
|       this.loadDB(); | ||||
|     } | ||||
|  | ||||
|     if (!this.db.idCounter) { | ||||
|       this.db.idCounter = 1; | ||||
|     } | ||||
|  | ||||
|     if (!this.db.users) { | ||||
|       this.db.users = []; | ||||
|       // TODO: remove defaults | ||||
|       this.createUser({ | ||||
|         name: 'admin', | ||||
|         password: 'admin', | ||||
|         role: UserRoles.Admin, | ||||
|       } as UserDTO); | ||||
|     } | ||||
|     this.saveDB(); | ||||
|   } | ||||
|  | ||||
|   public async findOne(filter: any): Promise<UserDTO> { | ||||
|     const result = await this.find(filter); | ||||
|  | ||||
|     if (result.length === 0) { | ||||
|       throw new Error('UserDTO not found'); | ||||
|     } | ||||
|     return result[0]; | ||||
|   } | ||||
|  | ||||
|   public async find(filter: any): Promise<UserDTO[]> { | ||||
|     const pass = filter.password; | ||||
|     delete filter.password; | ||||
|     const users = this.db.users.slice(); | ||||
|     let i = users.length; | ||||
|     while (i--) { | ||||
|       if (pass && !PasswordHelper.comparePassword(pass, users[i].password)) { | ||||
|         users.splice(i, 1); | ||||
|         continue; | ||||
|       } | ||||
|       if (Utils.equalsFilter(users[i], filter) === false) { | ||||
|         users.splice(i, 1); | ||||
|       } | ||||
|     } | ||||
|     return users; | ||||
|   } | ||||
|  | ||||
|   public async createUser(user: UserDTO): Promise<UserDTO> { | ||||
|     user.id = this.db.idCounter++; | ||||
|     user.password = PasswordHelper.cryptPassword(user.password); | ||||
|     this.db.users.push(user); | ||||
|     this.saveDB(); | ||||
|     return user; | ||||
|   } | ||||
|  | ||||
|   public async deleteUser(id: number): Promise<null | UserDTO> { | ||||
|     const deleted = this.db.users.filter((u: UserDTO): boolean => u.id === id); | ||||
|     this.db.users = this.db.users.filter((u: UserDTO): boolean => u.id !== id); | ||||
|     this.saveDB(); | ||||
|     if (deleted.length > 0) { | ||||
|       return deleted[0]; | ||||
|     } | ||||
|     return null; | ||||
|   } | ||||
|  | ||||
|   public async changeRole(id: number, newRole: UserRoles): Promise<UserDTO> { | ||||
|     for (const item of this.db.users) { | ||||
|       if (item.id === id) { | ||||
|         item.role = newRole; | ||||
|         this.saveDB(); | ||||
|         return item; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   private loadDB(): void { | ||||
|     const data = fs.readFileSync(this.dbPath, 'utf8'); | ||||
|     this.db = JSON.parse(data); | ||||
|   } | ||||
|  | ||||
|   private saveDB(): void { | ||||
|     fs.writeFileSync(this.dbPath, JSON.stringify(this.db)); | ||||
|   } | ||||
| } | ||||
| @@ -1,12 +0,0 @@ | ||||
| import { IVersionManager } from '../interfaces/IVersionManager'; | ||||
| import { DataStructureVersion } from '../../../../common/DataStructureVersion'; | ||||
|  | ||||
| export class VersionManager implements IVersionManager { | ||||
|   async getDataVersion(): Promise<string> { | ||||
|     return DataStructureVersion.toString(); | ||||
|   } | ||||
|  | ||||
|   async updateDataVersion(): Promise<void> { | ||||
|     return; | ||||
|   } | ||||
| } | ||||
| @@ -1,31 +0,0 @@ | ||||
| import { ParentDirectoryDTO } from '../../../../common/entities/DirectoryDTO'; | ||||
| import { IGalleryManager } from '../interfaces/IGalleryManager'; | ||||
| import { DuplicatesDTO } from '../../../../common/entities/DuplicatesDTO'; | ||||
| import { Connection } from 'typeorm'; | ||||
| import { DirectoryEntity } from './enitites/DirectoryEntity'; | ||||
| import { FileDTO } from '../../../../common/entities/FileDTO'; | ||||
|  | ||||
| export interface ISQLGalleryManager extends IGalleryManager { | ||||
|   listDirectory( | ||||
|     relativeDirectoryName: string, | ||||
|     knownLastModified?: number, | ||||
|     knownLastScanned?: number | ||||
|   ): Promise<ParentDirectoryDTO>; | ||||
|  | ||||
|   countDirectories(): Promise<number>; | ||||
|  | ||||
|   countPhotos(): Promise<number>; | ||||
|  | ||||
|   countVideos(): Promise<number>; | ||||
|  | ||||
|   countMediaSize(): Promise<number>; | ||||
|  | ||||
|   getPossibleDuplicates(): Promise<DuplicatesDTO[]>; | ||||
|  | ||||
|   selectDirStructure(directory: string): Promise<ParentDirectoryDTO<FileDTO>>; | ||||
|  | ||||
|   fillPreviewForSubDir( | ||||
|     connection: Connection, | ||||
|     dir: DirectoryEntity | ||||
|   ): Promise<void>; | ||||
| } | ||||
| @@ -1,5 +0,0 @@ | ||||
| import { IPersonManager } from '../interfaces/IPersonManager'; | ||||
|  | ||||
| export interface ISQLPersonManager extends IPersonManager { | ||||
|   countFaces(): Promise<number>; | ||||
| } | ||||
| @@ -1,28 +0,0 @@ | ||||
| import { | ||||
|   SearchQueryDTO, | ||||
|   SearchQueryTypes, | ||||
| } from '../../../../common/entities/SearchQueryDTO'; | ||||
| import { ISearchManager } from '../interfaces/ISearchManager'; | ||||
| import { AutoCompleteItem } from '../../../../common/entities/AutoCompleteItem'; | ||||
| import { SearchResultDTO } from '../../../../common/entities/SearchResultDTO'; | ||||
| import { PhotoDTO } from '../../../../common/entities/PhotoDTO'; | ||||
| import { Brackets } from 'typeorm'; | ||||
|  | ||||
| export interface ISQLSearchManager extends ISearchManager { | ||||
|   autocomplete( | ||||
|     text: string, | ||||
|     type: SearchQueryTypes | ||||
|   ): Promise<AutoCompleteItem[]>; | ||||
|  | ||||
|   search(query: SearchQueryDTO): Promise<SearchResultDTO>; | ||||
|  | ||||
|   getRandomPhoto(queryFilter: SearchQueryDTO): Promise<PhotoDTO>; | ||||
|  | ||||
|   // "Protected" functions. only called from other Managers, not from middlewares | ||||
|   getCount(query: SearchQueryDTO): Promise<number>; | ||||
|  | ||||
|   prepareAndBuildWhereQuery( | ||||
|     query: SearchQueryDTO, | ||||
|     directoryOnly?: boolean | ||||
|   ): Promise<Brackets>; | ||||
| } | ||||
| @@ -1,35 +0,0 @@ | ||||
| import { | ||||
|   Column, | ||||
|   Entity, | ||||
|   Index, | ||||
|   ManyToOne, | ||||
|   PrimaryGeneratedColumn, | ||||
|   TableInheritance, | ||||
| } from 'typeorm'; | ||||
| import { MediaEntity } from '../MediaEntity'; | ||||
| import { columnCharsetCS } from '../EntityUtils'; | ||||
| import { AlbumBaseDTO } from '../../../../../../common/entities/album/AlbumBaseDTO'; | ||||
|  | ||||
| @Entity() | ||||
| @TableInheritance({ column: { type: 'varchar', name: 'type', length: 24 } }) | ||||
| export class AlbumBaseEntity implements AlbumBaseDTO { | ||||
|   @Index() | ||||
|   @PrimaryGeneratedColumn({ unsigned: true }) | ||||
|   id: number; | ||||
|  | ||||
|   @Index() | ||||
|   @Column(columnCharsetCS) | ||||
|   name: string; | ||||
|  | ||||
|   /** | ||||
|    * Locked albums are not possible to remove | ||||
|    */ | ||||
|   @Column({ default: false }) | ||||
|   locked: boolean; | ||||
|  | ||||
|   @Column('int', { unsigned: true, default: 0 }) | ||||
|   count: number; | ||||
|  | ||||
|   @ManyToOne((type) => MediaEntity, { onDelete: 'SET NULL', nullable: true }) | ||||
|   public preview: MediaEntity; | ||||
| } | ||||
| @@ -1,7 +1,7 @@ | ||||
| import {Config, PrivateConfigClass} from '../../../common/config/private/Config'; | ||||
| import {Logger} from '../../Logger'; | ||||
| import {NotificationManager} from '../NotifocationManager'; | ||||
| import {SQLConnection} from '../database/sql/SQLConnection'; | ||||
| import {SQLConnection} from '../database/SQLConnection'; | ||||
| import * as fs from 'fs'; | ||||
| import {FFmpegFactory} from '../FFmpegFactory'; | ||||
| import { | ||||
| @@ -9,12 +9,9 @@ import { | ||||
|   ClientFacesConfig, | ||||
|   ClientMapConfig, | ||||
|   ClientMetaFileConfig, | ||||
|   ClientPhotoConfig, | ||||
|   ClientRandomPhotoConfig, | ||||
|   ClientSearchConfig, | ||||
|   ClientSharingConfig, | ||||
|   ClientThumbnailConfig, | ||||
|   ClientVideoConfig, | ||||
|   MapLayers, | ||||
|   MapProviders, | ||||
| } from '../../../common/config/public/ClientConfig'; | ||||
| @@ -22,17 +19,12 @@ import { | ||||
|   DatabaseType, | ||||
|   ServerDataBaseConfig, | ||||
|   ServerJobConfig, | ||||
|   ServerMetaFileConfig, | ||||
|   ServerPhotoConfig, | ||||
|   ServerPreviewConfig, | ||||
|   ServerThumbnailConfig, | ||||
|   ServerVideoConfig, | ||||
| } from '../../../common/config/private/PrivateConfig'; | ||||
| import {SearchQueryParser} from '../../../common/SearchQueryParser'; | ||||
| import { | ||||
|   SearchQueryTypes, | ||||
|   TextSearch, | ||||
| } from '../../../common/entities/SearchQueryDTO'; | ||||
| import {SearchQueryTypes, TextSearch,} from '../../../common/entities/SearchQueryDTO'; | ||||
| import {Utils} from '../../../common/Utils'; | ||||
|  | ||||
| const LOG_TAG = '[ConfigDiagnostics]'; | ||||
| @@ -42,12 +34,7 @@ export class ConfigDiagnostics { | ||||
|     albumConfig: ClientAlbumConfig, | ||||
|     original: PrivateConfigClass | ||||
|   ): void { | ||||
|     if ( | ||||
|       albumConfig.enabled === true && | ||||
|       original.Database.type === DatabaseType.memory | ||||
|     ) { | ||||
|       throw new Error('Memory Database does not support albums'); | ||||
|     } | ||||
|     // nothing to check | ||||
|   } | ||||
|  | ||||
|   static checkReadWritePermission(path: string): Promise<void> { | ||||
| @@ -65,9 +52,7 @@ export class ConfigDiagnostics { | ||||
|   static async testDatabase( | ||||
|     databaseConfig: ServerDataBaseConfig | ||||
|   ): Promise<void> { | ||||
|     if (databaseConfig.type !== DatabaseType.memory) { | ||||
|     await SQLConnection.tryConnection(databaseConfig); | ||||
|     } | ||||
|     if (databaseConfig.type === DatabaseType.sqlite) { | ||||
|       try { | ||||
|         await this.checkReadWritePermission( | ||||
| @@ -199,9 +184,6 @@ export class ConfigDiagnostics { | ||||
|     config: PrivateConfigClass | ||||
|   ): Promise<void> { | ||||
|     if (faces.enabled === true) { | ||||
|       if (config.Database.type === DatabaseType.memory) { | ||||
|         throw new Error('Memory Database do not support faces'); | ||||
|       } | ||||
|       if (config.Search.enabled === false) { | ||||
|         throw new Error('Faces support needs enabled search'); | ||||
|       } | ||||
| @@ -212,24 +194,13 @@ export class ConfigDiagnostics { | ||||
|     search: ClientSearchConfig, | ||||
|     config: PrivateConfigClass | ||||
|   ): Promise<void> { | ||||
|     if ( | ||||
|       search.enabled === true && | ||||
|       config.Database.type === DatabaseType.memory | ||||
|     ) { | ||||
|       throw new Error('Memory Database do not support searching'); | ||||
|     } | ||||
|     //nothing to check | ||||
|   } | ||||
|  | ||||
|   static async testSharingConfig( | ||||
|     sharing: ClientSharingConfig, | ||||
|     config: PrivateConfigClass | ||||
|   ): Promise<void> { | ||||
|     if ( | ||||
|       sharing.enabled === true && | ||||
|       config.Database.type === DatabaseType.memory | ||||
|     ) { | ||||
|       throw new Error('Memory Database do not support sharing'); | ||||
|     } | ||||
|     if ( | ||||
|       sharing.enabled === true && | ||||
|       config.Users.authenticationRequired === false | ||||
| @@ -242,12 +213,7 @@ export class ConfigDiagnostics { | ||||
|     sharing: ClientRandomPhotoConfig, | ||||
|     config: PrivateConfigClass | ||||
|   ): Promise<void> { | ||||
|     if ( | ||||
|       sharing.enabled === true && | ||||
|       config.Database.type === DatabaseType.memory | ||||
|     ) { | ||||
|       throw new Error('Memory Database do not support random photo'); | ||||
|     } | ||||
|     //nothing to check | ||||
|   } | ||||
|  | ||||
|   static async testMapConfig(map: ClientMapConfig): Promise<void> { | ||||
| @@ -308,7 +274,6 @@ export class ConfigDiagnostics { | ||||
|   } | ||||
|  | ||||
|   static async runDiagnostics(): Promise<void> { | ||||
|     if (Config.Database.type !== DatabaseType.memory) { | ||||
|     try { | ||||
|       await ConfigDiagnostics.testDatabase(Config.Database); | ||||
|     } catch (ex) { | ||||
| @@ -320,7 +285,6 @@ export class ConfigDiagnostics { | ||||
|       ); | ||||
|       process.exit(1); | ||||
|     } | ||||
|     } | ||||
|  | ||||
|     try { | ||||
|       await ConfigDiagnostics.testSharp(); | ||||
|   | ||||
| @@ -12,7 +12,7 @@ import { | ||||
| import {ITaskExecuter, TaskExecuter} from '../threading/TaskExecuter'; | ||||
| import {FaceRegion, PhotoDTO} from '../../../common/entities/PhotoDTO'; | ||||
| import {SupportedFormats} from '../../../common/SupportedFormats'; | ||||
| import {PersonEntry} from '../database/sql/enitites/PersonEntry'; | ||||
| import {PersonEntry} from '../database/enitites/PersonEntry'; | ||||
|  | ||||
| export class PhotoProcessing { | ||||
|   private static initDone = false; | ||||
|   | ||||
| @@ -1,17 +1,8 @@ | ||||
| import { IJobManager } from '../database/interfaces/IJobManager'; | ||||
| import { | ||||
|   JobProgressDTO, | ||||
|   JobProgressStates, | ||||
| } from '../../../common/entities/job/JobProgressDTO'; | ||||
| import {JobProgressDTO, JobProgressStates,} from '../../../common/entities/job/JobProgressDTO'; | ||||
| import {IJob} from './jobs/IJob'; | ||||
| import {JobRepository} from './JobRepository'; | ||||
| import {Config} from '../../../common/config/private/Config'; | ||||
| import { | ||||
|   AfterJobTrigger, | ||||
|   JobScheduleDTO, | ||||
|   JobScheduleDTOUtils, | ||||
|   JobTriggerType, | ||||
| } from '../../../common/entities/job/JobScheduleDTO'; | ||||
| import {AfterJobTrigger, JobScheduleDTO, JobScheduleDTOUtils, JobTriggerType,} from '../../../common/entities/job/JobScheduleDTO'; | ||||
| import {Logger} from '../../Logger'; | ||||
| import {NotificationManager} from '../NotifocationManager'; | ||||
| import {IJobListener} from './jobs/IJobListener'; | ||||
| @@ -20,7 +11,7 @@ import { JobProgressManager } from './JobProgressManager'; | ||||
|  | ||||
| const LOG_TAG = '[JobManager]'; | ||||
|  | ||||
| export class JobManager implements IJobManager, IJobListener { | ||||
| export class JobManager implements IJobListener { | ||||
|   protected timers: { schedule: JobScheduleDTO; timer: NodeJS.Timeout }[] = []; | ||||
|   protected progressManager: JobProgressManager = null; | ||||
|  | ||||
| @@ -59,7 +50,7 @@ export class JobManager implements IJobManager, IJobListener { | ||||
|       (allowParallelRun === false && this.JobRunning === true) || | ||||
|       this.JobNoParallelRunning === true | ||||
|     ) { | ||||
|       throw new Error("Can't start this job while another is running"); | ||||
|       throw new Error('Can\'t start this job while another is running'); | ||||
|     } | ||||
|  | ||||
|     const t = this.findJob(jobName); | ||||
|   | ||||
| @@ -13,7 +13,7 @@ export class DBRestJob extends Job { | ||||
|   protected readonly IsInstant = true; | ||||
|  | ||||
|   public get Supported(): boolean { | ||||
|     return Config.Database.type !== DatabaseType.memory; | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   protected async init(): Promise<void> { | ||||
|   | ||||
| @@ -6,14 +6,13 @@ import {DirectoryScanSettings} from '../../threading/DiskMangerWorker'; | ||||
| import {Logger} from '../../../Logger'; | ||||
| import {Config} from '../../../../common/config/private/Config'; | ||||
| import {FileDTO} from '../../../../common/entities/FileDTO'; | ||||
| import {SQLConnection} from '../../database/sql/SQLConnection'; | ||||
| import {MediaEntity} from '../../database/sql/enitites/MediaEntity'; | ||||
| import {PhotoEntity} from '../../database/sql/enitites/PhotoEntity'; | ||||
| import {VideoEntity} from '../../database/sql/enitites/VideoEntity'; | ||||
| import {SQLConnection} from '../../database/SQLConnection'; | ||||
| import {MediaEntity} from '../../database/enitites/MediaEntity'; | ||||
| import {PhotoEntity} from '../../database/enitites/PhotoEntity'; | ||||
| import {VideoEntity} from '../../database/enitites/VideoEntity'; | ||||
| import {backendTexts} from '../../../../common/BackendTexts'; | ||||
| import {ProjectPath} from '../../../ProjectPath'; | ||||
| import {DatabaseType} from '../../../../common/config/private/PrivateConfig'; | ||||
| import {FileEntity} from '../../database/sql/enitites/FileEntity'; | ||||
| import {FileEntity} from '../../database/enitites/FileEntity'; | ||||
| import {DirectoryBaseDTO, DirectoryDTOUtils} from '../../../../common/entities/DirectoryDTO'; | ||||
|  | ||||
| const LOG_TAG = '[FileJob]'; | ||||
| @@ -35,7 +34,6 @@ export abstract class FileJob<S extends { indexedOnly?: boolean } = { indexedOnl | ||||
|   protected constructor(private scanFilter: DirectoryScanSettings) { | ||||
|     super(); | ||||
|     this.scanFilter.noChildDirPhotos = true; | ||||
|     if (Config.Database.type !== DatabaseType.memory) { | ||||
|     this.ConfigTemplate.push({ | ||||
|       id: 'indexedOnly', | ||||
|       type: 'boolean', | ||||
| @@ -43,7 +41,7 @@ export abstract class FileJob<S extends { indexedOnly?: boolean } = { indexedOnl | ||||
|       description: backendTexts.indexedFilesOnly.description, | ||||
|       defaultValue: true, | ||||
|     }); | ||||
|     } | ||||
|  | ||||
|   } | ||||
|  | ||||
|   protected async init(): Promise<void> { | ||||
| @@ -70,12 +68,10 @@ export abstract class FileJob<S extends { indexedOnly?: boolean } = { indexedOnl | ||||
|   protected abstract processFile(filePath: string): Promise<void>; | ||||
|  | ||||
|   protected async step(): Promise<boolean> { | ||||
|     const DBBased = this.config.indexedOnly && | ||||
|       Config.Database.type !== DatabaseType.memory; | ||||
|     if ( | ||||
|       this.fileQueue.length === 0 && | ||||
|       ((this.directoryQueue.length === 0 && !DBBased) || | ||||
|         (DBBased && | ||||
|       ((this.directoryQueue.length === 0 && !this.config.indexedOnly) || | ||||
|         (this.config.indexedOnly && | ||||
|           this.DBProcessing.hasMoreMedia === false))) { | ||||
|       return false; | ||||
|     } | ||||
| @@ -103,7 +99,7 @@ export abstract class FileJob<S extends { indexedOnly?: boolean } = { indexedOnl | ||||
|       } | ||||
|     }; | ||||
|  | ||||
|     if (!DBBased) { | ||||
|     if (!this.config.indexedOnly) { | ||||
|       if (this.directoryQueue.length > 0) { | ||||
|         await this.loadADirectoryFromDisk(); | ||||
|       } else if (this.fileQueue.length > 0) { | ||||
|   | ||||
| @@ -1,19 +1,13 @@ | ||||
| import {ObjectManagers} from '../../ObjectManagers'; | ||||
| import * as path from 'path'; | ||||
| import * as fs from 'fs'; | ||||
| import { Config } from '../../../../common/config/private/Config'; | ||||
| import {Job} from './Job'; | ||||
| import { | ||||
|   ConfigTemplateEntry, | ||||
|   DefaultsJobs, | ||||
| } from '../../../../common/entities/job/JobDTO'; | ||||
| import {ConfigTemplateEntry, DefaultsJobs,} from '../../../../common/entities/job/JobDTO'; | ||||
| import {JobProgressStates} from '../../../../common/entities/job/JobProgressDTO'; | ||||
| import { DatabaseType } from '../../../../common/config/private/PrivateConfig'; | ||||
| import {DiskMangerWorker} from '../../threading/DiskMangerWorker'; | ||||
| import {ProjectPath} from '../../../ProjectPath'; | ||||
| import {backendTexts} from '../../../../common/BackendTexts'; | ||||
| import {ParentDirectoryDTO} from '../../../../common/entities/DirectoryDTO'; | ||||
| import { ISQLGalleryManager } from '../../database/sql/IGalleryManager'; | ||||
| import {Logger} from '../../../Logger'; | ||||
| import {FileDTO} from '../../../../common/entities/FileDTO'; | ||||
|  | ||||
| @@ -33,7 +27,7 @@ export class IndexingJob< | ||||
|   ]; | ||||
|  | ||||
|   public get Supported(): boolean { | ||||
|     return Config.Database.type !== DatabaseType.memory; | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   protected async init(): Promise<void> { | ||||
| @@ -58,9 +52,7 @@ export class IndexingJob< | ||||
|     if (this.config.indexChangesOnly) { | ||||
|       const stat = fs.statSync(path.join(ProjectPath.ImageFolder, directory)); | ||||
|       const lastModified = DiskMangerWorker.calcLastModified(stat); | ||||
|       scanned = await ( | ||||
|         ObjectManagers.getInstance().GalleryManager as ISQLGalleryManager | ||||
|       ).selectDirStructure(directory); | ||||
|       scanned = await ObjectManagers.getInstance().GalleryManager.selectDirStructure(directory); | ||||
|       // If not modified and it was scanned before, dir is up-to-date | ||||
|       if ( | ||||
|         scanned && | ||||
|   | ||||
| @@ -14,7 +14,7 @@ export class PreviewFillingJob extends Job { | ||||
|   status: 'Persons' | 'Albums' | 'Directory' = 'Persons'; | ||||
|  | ||||
|   public get Supported(): boolean { | ||||
|     return Config.Database.type !== DatabaseType.memory; | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   protected async init(): Promise<void> { | ||||
|   | ||||
| @@ -13,7 +13,7 @@ export class PreviewRestJob extends Job { | ||||
|   protected readonly IsInstant = true; | ||||
|  | ||||
|   public get Supported(): boolean { | ||||
|     return Config.Database.type !== DatabaseType.memory; | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   protected async init(): Promise<void> { | ||||
|   | ||||
| @@ -117,11 +117,7 @@ export class Server { | ||||
|     Localizations.init(); | ||||
|  | ||||
|     this.app.use(locale(Config.Server.languages, 'en')); | ||||
|     if (Config.Database.type !== DatabaseType.memory) { | ||||
|     await ObjectManagers.InitSQLManagers(); | ||||
|     } else { | ||||
|       await ObjectManagers.InitMemoryManagers(); | ||||
|     } | ||||
|  | ||||
|     Router.route(this.app); | ||||
|  | ||||
|   | ||||
| @@ -41,7 +41,6 @@ if (typeof $localize === 'undefined') { | ||||
|  | ||||
|  | ||||
| export enum DatabaseType { | ||||
|   memory = 1, | ||||
|   mysql = 2, | ||||
|   sqlite = 3, | ||||
| } | ||||
| @@ -221,17 +220,13 @@ export class UserConfig { | ||||
| export class ServerDataBaseConfig { | ||||
|   @ConfigProperty<DatabaseType, ServerConfig>({ | ||||
|     type: DatabaseType, | ||||
|     onNewValue: (value, config) => { | ||||
|       if (config && value === DatabaseType.memory) { | ||||
|         config.Search.enabled = false; | ||||
|         config.Sharing.enabled = false; | ||||
|       } | ||||
|     }, | ||||
|     tags: | ||||
|       { | ||||
|         name: $localize`Type`, | ||||
|         priority: ConfigPriority.advanced | ||||
|       }, | ||||
|         priority: ConfigPriority.advanced, | ||||
|         githubIssue: 573 | ||||
|       } as TAGS, | ||||
|     description: $localize`SQLite is recommended.` | ||||
|   }) | ||||
|   type: DatabaseType = DatabaseType.sqlite; | ||||
|  | ||||
| @@ -616,7 +611,8 @@ export class ServerJobConfig { | ||||
|     arrayType: JobScheduleConfig, | ||||
|     tags: { | ||||
|       name: $localize`Scheduled jobs`, | ||||
|       priority: ConfigPriority.advanced} | ||||
|       priority: ConfigPriority.advanced | ||||
|     } | ||||
|   }) | ||||
|   scheduled: JobScheduleConfig[] = [ | ||||
|     new JobScheduleConfig( | ||||
|   | ||||
| @@ -3,10 +3,10 @@ import { | ||||
|   GPSMetadataEntity, | ||||
|   MediaDimensionEntity, | ||||
|   PositionMetaDataEntity | ||||
| } from '../src/backend/model/database/sql/enitites/MediaEntity'; | ||||
| import {PhotoEntity, PhotoMetadataEntity} from '../src/backend/model/database/sql/enitites/PhotoEntity'; | ||||
| import {DirectoryEntity} from '../src/backend/model/database/sql/enitites/DirectoryEntity'; | ||||
| import {VideoEntity, VideoMetadataEntity} from '../src/backend/model/database/sql/enitites/VideoEntity'; | ||||
| } from '../src/backend/model/database/enitites/MediaEntity'; | ||||
| import {PhotoEntity, PhotoMetadataEntity} from '../src/backend/model/database/enitites/PhotoEntity'; | ||||
| import {DirectoryEntity} from '../src/backend/model/database/enitites/DirectoryEntity'; | ||||
| import {VideoEntity, VideoMetadataEntity} from '../src/backend/model/database/enitites/VideoEntity'; | ||||
| import {MediaDimension, MediaDTO} from '../src/common/entities/MediaDTO'; | ||||
| import { | ||||
|   CameraMetadata, | ||||
|   | ||||
| @@ -1,14 +1,14 @@ | ||||
| import {Config} from '../../src/common/config/private/Config'; | ||||
| import * as path from 'path'; | ||||
| import * as fs from 'fs'; | ||||
| import {SQLConnection} from '../../src/backend/model/database/sql/SQLConnection'; | ||||
| import {SQLConnection} from '../../src/backend/model/database/SQLConnection'; | ||||
| import {DatabaseType} from '../../src/common/config/private/PrivateConfig'; | ||||
| import {ProjectPath} from '../../src/backend/ProjectPath'; | ||||
| import {DirectoryBaseDTO, ParentDirectoryDTO, SubDirectoryDTO} from '../../src/common/entities/DirectoryDTO'; | ||||
| import {ObjectManagers} from '../../src/backend/model/ObjectManagers'; | ||||
| import {DiskMangerWorker} from '../../src/backend/model/threading/DiskMangerWorker'; | ||||
| import {IndexingManager} from '../../src/backend/model/database/sql/IndexingManager'; | ||||
| import {GalleryManager} from '../../src/backend/model/database/sql/GalleryManager'; | ||||
| import {IndexingManager} from '../../src/backend/model/database/IndexingManager'; | ||||
| import {GalleryManager} from '../../src/backend/model/database/GalleryManager'; | ||||
| import {Connection} from 'typeorm'; | ||||
| import {Utils} from '../../src/common/Utils'; | ||||
| import {TestHelper} from '../TestHelper'; | ||||
| @@ -43,7 +43,6 @@ const LOG_TAG = 'DBTestHelper'; | ||||
| export class DBTestHelper { | ||||
|  | ||||
|   static enable = { | ||||
|     memory: false, | ||||
|     sqlite: process.env.TEST_SQLITE !== 'false', | ||||
|     mysql: process.env.TEST_MYSQL !== 'false' | ||||
|   }; | ||||
| @@ -108,12 +107,6 @@ export class DBTestHelper { | ||||
|             return tests(helper); | ||||
|           }); | ||||
|         } | ||||
|         if (settings.memory) { | ||||
|           const helper = new DBTestHelper(DatabaseType.memory); | ||||
|           savedDescribe('memory', () => { | ||||
|             return tests(helper); | ||||
|           }); | ||||
|         } | ||||
|       }); | ||||
|     }; | ||||
|   } | ||||
| @@ -159,8 +152,6 @@ export class DBTestHelper { | ||||
|       await this.initSQLite(); | ||||
|     } else if (this.dbType === DatabaseType.mysql) { | ||||
|       await this.initMySQL(); | ||||
|     } else if (this.dbType === DatabaseType.memory) { | ||||
|       Config.Database.type = DatabaseType.memory; | ||||
|     } | ||||
|   } | ||||
|  | ||||
| @@ -169,8 +160,6 @@ export class DBTestHelper { | ||||
|       await this.clearUpSQLite(); | ||||
|     } else if (this.dbType === DatabaseType.mysql) { | ||||
|       await this.clearUpMysql(); | ||||
|     } else if (this.dbType === DatabaseType.memory) { | ||||
|       await this.clearUpMemory(); | ||||
|     } | ||||
|   } | ||||
|  | ||||
| @@ -242,7 +231,4 @@ export class DBTestHelper { | ||||
|     await fs.promises.rm(this.tempDir, {recursive: true, force: true}); | ||||
|   } | ||||
|  | ||||
|   private async clearUpMemory(): Promise<void> { | ||||
|     return this.resetSQLite(); | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -2,19 +2,19 @@ import {expect} from 'chai'; | ||||
| import * as path from 'path'; | ||||
| import * as fs from 'fs'; | ||||
| import {Config} from '../../../../../src/common/config/private/Config'; | ||||
| import {SQLConnection} from '../../../../../src/backend/model/database/sql/SQLConnection'; | ||||
| import {UserEntity} from '../../../../../src/backend/model/database/sql/enitites/UserEntity'; | ||||
| import {SQLConnection} from '../../../../../src/backend/model/database/SQLConnection'; | ||||
| import {UserEntity} from '../../../../../src/backend/model/database/enitites/UserEntity'; | ||||
| import {UserRoles} from '../../../../../src/common/entities/UserDTO'; | ||||
| import {PasswordHelper} from '../../../../../src/backend/model/PasswordHelper'; | ||||
| import {DirectoryEntity} from '../../../../../src/backend/model/database/sql/enitites/DirectoryEntity'; | ||||
| import {PhotoEntity, PhotoMetadataEntity} from '../../../../../src/backend/model/database/sql/enitites/PhotoEntity'; | ||||
| import {DirectoryEntity} from '../../../../../src/backend/model/database/enitites/DirectoryEntity'; | ||||
| import {PhotoEntity, PhotoMetadataEntity} from '../../../../../src/backend/model/database/enitites/PhotoEntity'; | ||||
| import { | ||||
|   CameraMetadataEntity, | ||||
|   GPSMetadataEntity, | ||||
|   MediaDimensionEntity, | ||||
|   PositionMetaDataEntity | ||||
| } from '../../../../../src/backend/model/database/sql/enitites/MediaEntity'; | ||||
| import {VersionEntity} from '../../../../../src/backend/model/database/sql/enitites/VersionEntity'; | ||||
| } from '../../../../../src/backend/model/database/enitites/MediaEntity'; | ||||
| import {VersionEntity} from '../../../../../src/backend/model/database/enitites/VersionEntity'; | ||||
| import {DatabaseType} from '../../../../../src/common/config/private/PrivateConfig'; | ||||
| import {ProjectPath} from '../../../../../src/backend/ProjectPath'; | ||||
|  | ||||
| @@ -46,7 +46,7 @@ describe('Typeorm integration', () => { | ||||
|   }); | ||||
|  | ||||
|  | ||||
|   const getDir = (namePrefix: string = '') => { | ||||
|   const getDir = (namePrefix = '') => { | ||||
|     const d = new DirectoryEntity(); | ||||
|     d.name = namePrefix + 'test dir'; | ||||
|     d.path = '.'; | ||||
|   | ||||
| @@ -4,7 +4,7 @@ import {LoginCredential} from '../../../../src/common/entities/LoginCredential'; | ||||
| import {UserDTO, UserRoles} from '../../../../src/common/entities/UserDTO'; | ||||
| import * as path from 'path'; | ||||
| import * as fs from 'fs'; | ||||
| import {SQLConnection} from '../../../../src/backend/model/database/sql/SQLConnection'; | ||||
| import {SQLConnection} from '../../../../src/backend/model/database/SQLConnection'; | ||||
| import {ObjectManagers} from '../../../../src/backend/model/ObjectManagers'; | ||||
| import {Utils} from '../../../../src/common/Utils'; | ||||
| import {SuperAgentStatic} from 'superagent'; | ||||
|   | ||||
| @@ -4,7 +4,7 @@ import {LoginCredential} from '../../../../src/common/entities/LoginCredential'; | ||||
| import {UserDTO, UserRoles} from '../../../../src/common/entities/UserDTO'; | ||||
| import * as path from 'path'; | ||||
| import * as fs from 'fs'; | ||||
| import {SQLConnection} from '../../../../src/backend/model/database/sql/SQLConnection'; | ||||
| import {SQLConnection} from '../../../../src/backend/model/database/SQLConnection'; | ||||
| import {ObjectManagers} from '../../../../src/backend/model/ObjectManagers'; | ||||
| import {QueryParams} from '../../../../src/common/QueryParams'; | ||||
| import {Utils} from '../../../../src/common/Utils'; | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| import * as path from 'path'; | ||||
| import * as fs from 'fs'; | ||||
| import {Config} from '../../../../../src/common/config/private/Config'; | ||||
| import {SQLConnection} from '../../../../../src/backend/model/database/sql/SQLConnection'; | ||||
| import {SQLConnection} from '../../../../../src/backend/model/database/SQLConnection'; | ||||
| import {Server} from '../../../../../src/backend/server'; | ||||
| import {DatabaseType, ServerConfig} from '../../../../../src/common/config/private/PrivateConfig'; | ||||
| import {ProjectPath} from '../../../../../src/backend/ProjectPath'; | ||||
|   | ||||
| @@ -4,10 +4,9 @@ import {AuthenticationMWs} from '../../../../../src/backend/middlewares/user/Aut | ||||
| import {ErrorCodes, ErrorDTO} from '../../../../../src/common/entities/Error'; | ||||
| import {UserDTO, UserRoles} from '../../../../../src/common/entities/UserDTO'; | ||||
| import {ObjectManagers} from '../../../../../src/backend/model/ObjectManagers'; | ||||
| import {UserManager} from '../../../../../src/backend/model/database/memory/UserManager'; | ||||
| import {Config} from '../../../../../src/common/config/private/Config'; | ||||
| import {IUserManager} from '../../../../../src/backend/model/database/interfaces/IUserManager'; | ||||
| import * as path from 'path'; | ||||
| import {UserManager} from '../../../../../src/backend/model/database/UserManager'; | ||||
|  | ||||
|  | ||||
| declare const describe: any; | ||||
| @@ -53,6 +52,7 @@ describe('Authentication middleware', () => { | ||||
|       }; | ||||
|       AuthenticationMWs.authenticate(req, { | ||||
|         status: () => { | ||||
|           // empty | ||||
|         } | ||||
|       } as any, next); | ||||
|  | ||||
| @@ -254,7 +254,7 @@ describe('Authentication middleware', () => { | ||||
|         done(); | ||||
|       }; | ||||
|       ObjectManagers.getInstance().UserManager = { | ||||
|         findOne: (filter): Promise<UserDTO> => { | ||||
|         findOne: (_: never): Promise<UserDTO> => { | ||||
|           return Promise.reject(null); | ||||
|         } | ||||
|       } as UserManager; | ||||
| @@ -281,10 +281,10 @@ describe('Authentication middleware', () => { | ||||
|         done(); | ||||
|       }; | ||||
|       ObjectManagers.getInstance().UserManager = { | ||||
|         findOne: (filter) => { | ||||
|         findOne: (filter: never) => { | ||||
|           return Promise.resolve('test user' as any); | ||||
|         } | ||||
|       } as IUserManager; | ||||
|       } as UserManager; | ||||
|       AuthenticationMWs.login(req, null, next); | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -1,10 +1,10 @@ | ||||
| import {DBTestHelper} from '../../../DBTestHelper'; | ||||
| import {ParentDirectoryDTO, SubDirectoryDTO} from '../../../../../src/common/entities/DirectoryDTO'; | ||||
| import {ParentDirectoryDTO} from '../../../../../src/common/entities/DirectoryDTO'; | ||||
| import {ObjectManagers} from '../../../../../src/backend/model/ObjectManagers'; | ||||
| import {AlbumManager} from '../../../../../src/backend/model/database/sql/AlbumManager'; | ||||
| import {AlbumManager} from '../../../../../src/backend/model/database/AlbumManager'; | ||||
| import {SearchQueryTypes, TextSearch} from '../../../../../src/common/entities/SearchQueryDTO'; | ||||
| import {SQLConnection} from '../../../../../src/backend/model/database/sql/SQLConnection'; | ||||
| import {AlbumBaseEntity} from '../../../../../src/backend/model/database/sql/enitites/album/AlbumBaseEntity'; | ||||
| import {SQLConnection} from '../../../../../src/backend/model/database/SQLConnection'; | ||||
| import {AlbumBaseEntity} from '../../../../../src/backend/model/database/enitites/album/AlbumBaseEntity'; | ||||
| import {Utils} from '../../../../../src/common/Utils'; | ||||
| import {MediaDTO} from '../../../../../src/common/entities/MediaDTO'; | ||||
| import {SavedSearchDTO} from '../../../../../src/common/entities/album/SavedSearchDTO'; | ||||
| @@ -30,7 +30,6 @@ describe('AlbumManager', (sqlHelper: DBTestHelper) => { | ||||
|   describe = tmpDescribe; | ||||
|  | ||||
|  | ||||
|  | ||||
|   const setUpSqlDB = async () => { | ||||
|     await sqlHelper.initDB(); | ||||
|     await sqlHelper.setUpTestGallery(); | ||||
|   | ||||
| @@ -1,8 +1,5 @@ | ||||
| import {DBTestHelper} from '../../../DBTestHelper'; | ||||
| import {GalleryManager} from '../../../../../src/backend/model/database/sql/GalleryManager'; | ||||
| import {ObjectManagers} from '../../../../../src/backend/model/ObjectManagers'; | ||||
| import {SQLConnection} from '../../../../../src/backend/model/database/sql/SQLConnection'; | ||||
| import {DirectoryEntity} from '../../../../../src/backend/model/database/sql/enitites/DirectoryEntity'; | ||||
| import {GalleryManager} from '../../../../../src/backend/model/database/GalleryManager'; | ||||
| import {ParentDirectoryDTO} from '../../../../../src/common/entities/DirectoryDTO'; | ||||
| import {Connection} from 'typeorm'; | ||||
|  | ||||
|   | ||||
| @@ -1,23 +1,23 @@ | ||||
| import * as fs from 'fs'; | ||||
| import {Config} from '../../../../../src/common/config/private/Config'; | ||||
| import {SQLConnection} from '../../../../../src/backend/model/database/sql/SQLConnection'; | ||||
| import {GalleryManager} from '../../../../../src/backend/model/database/sql/GalleryManager'; | ||||
| import {SQLConnection} from '../../../../../src/backend/model/database/SQLConnection'; | ||||
| import {GalleryManager} from '../../../../../src/backend/model/database/GalleryManager'; | ||||
| import {DirectoryBaseDTO, DirectoryDTOUtils, ParentDirectoryDTO} from '../../../../../src/common/entities/DirectoryDTO'; | ||||
| import {TestHelper} from '../../../../TestHelper'; | ||||
| import {Connection} from 'typeorm'; | ||||
| import {Utils} from '../../../../../src/common/Utils'; | ||||
| import {MediaDTO} from '../../../../../src/common/entities/MediaDTO'; | ||||
| import {FileDTO} from '../../../../../src/common/entities/FileDTO'; | ||||
| import {IndexingManager} from '../../../../../src/backend/model/database/sql/IndexingManager'; | ||||
| import {IndexingManager} from '../../../../../src/backend/model/database/IndexingManager'; | ||||
| import {ObjectManagers} from '../../../../../src/backend/model/ObjectManagers'; | ||||
| import {DBTestHelper} from '../../../DBTestHelper'; | ||||
| import {DiskMangerWorker} from '../../../../../src/backend/model/threading/DiskMangerWorker'; | ||||
| import {ReIndexingSensitivity, SQLLogLevel} from '../../../../../src/common/config/private/PrivateConfig'; | ||||
| import {ReIndexingSensitivity} from '../../../../../src/common/config/private/PrivateConfig'; | ||||
| import {SearchQueryTypes, TextSearch, TextSearchQueryMatchTypes} from '../../../../../src/common/entities/SearchQueryDTO'; | ||||
| import {ProjectPath} from '../../../../../src/backend/ProjectPath'; | ||||
| import * as path from 'path'; | ||||
| import {DiskManager} from '../../../../../src/backend/model/DiskManger'; | ||||
| import {AlbumManager} from '../../../../../src/backend/model/database/sql/AlbumManager'; | ||||
| import {AlbumManager} from '../../../../../src/backend/model/database/AlbumManager'; | ||||
| import {SortingMethods} from '../../../../../src/common/entities/SortingMethods'; | ||||
|  | ||||
| // eslint-disable-next-line @typescript-eslint/no-var-requires | ||||
|   | ||||
| @@ -1,13 +1,13 @@ | ||||
| import {expect} from 'chai'; | ||||
| import {PersonManager} from '../../../../../src/backend/model/database/sql/PersonManager'; | ||||
| import {PersonManager} from '../../../../../src/backend/model/database/PersonManager'; | ||||
| import {DBTestHelper} from '../../../DBTestHelper'; | ||||
| import {TestHelper} from '../../../../TestHelper'; | ||||
| import {PhotoDTO} from '../../../../../src/common/entities/PhotoDTO'; | ||||
| import {Utils} from '../../../../../src/common/Utils'; | ||||
| import {ParentDirectoryDTO} from '../../../../../src/common/entities/DirectoryDTO'; | ||||
| import {VideoDTO} from '../../../../../src/common/entities/VideoDTO'; | ||||
| import {SQLConnection} from '../../../../../src/backend/model/database/sql/SQLConnection'; | ||||
| import {PersonEntry} from '../../../../../src/backend/model/database/sql/enitites/PersonEntry'; | ||||
| import {SQLConnection} from '../../../../../src/backend/model/database/SQLConnection'; | ||||
| import {PersonEntry} from '../../../../../src/backend/model/database/enitites/PersonEntry'; | ||||
|  | ||||
|  | ||||
| // to help WebStorm to handle the test cases | ||||
|   | ||||
| @@ -1,21 +1,21 @@ | ||||
| import {SearchManager} from '../../../../../src/backend/model/database/sql/SearchManager'; | ||||
| import {SearchManager} from '../../../../../src/backend/model/database/SearchManager'; | ||||
| import {DBTestHelper} from '../../../DBTestHelper'; | ||||
| import {SearchQueryDTO, SearchQueryTypes, TextSearch} from '../../../../../src/common/entities/SearchQueryDTO'; | ||||
| import {IndexingManager} from '../../../../../src/backend/model/database/sql/IndexingManager'; | ||||
| import {IndexingManager} from '../../../../../src/backend/model/database/IndexingManager'; | ||||
| import {DirectoryBaseDTO, ParentDirectoryDTO, SubDirectoryDTO} from '../../../../../src/common/entities/DirectoryDTO'; | ||||
| import {TestHelper} from '../../../../TestHelper'; | ||||
| import {ObjectManagers} from '../../../../../src/backend/model/ObjectManagers'; | ||||
| import {GalleryManager} from '../../../../../src/backend/model/database/sql/GalleryManager'; | ||||
| import {GalleryManager} from '../../../../../src/backend/model/database/GalleryManager'; | ||||
| import {Connection} from 'typeorm'; | ||||
| import {PhotoDTO} from '../../../../../src/common/entities/PhotoDTO'; | ||||
| import {VideoDTO} from '../../../../../src/common/entities/VideoDTO'; | ||||
| import {FileDTO} from '../../../../../src/common/entities/FileDTO'; | ||||
| import {PreviewManager} from '../../../../../src/backend/model/database/sql/PreviewManager'; | ||||
| import {PreviewManager} from '../../../../../src/backend/model/database/PreviewManager'; | ||||
| import {Config} from '../../../../../src/common/config/private/Config'; | ||||
| import {SortingMethods} from '../../../../../src/common/entities/SortingMethods'; | ||||
| import {Utils} from '../../../../../src/common/Utils'; | ||||
| import {SQLConnection} from '../../../../../src/backend/model/database/sql/SQLConnection'; | ||||
| import {DirectoryEntity} from '../../../../../src/backend/model/database/sql/enitites/DirectoryEntity'; | ||||
| import {SQLConnection} from '../../../../../src/backend/model/database/SQLConnection'; | ||||
| import {DirectoryEntity} from '../../../../../src/backend/model/database/enitites/DirectoryEntity'; | ||||
|  | ||||
| // eslint-disable-next-line @typescript-eslint/no-var-requires | ||||
| const deepEqualInAnyOrder = require('deep-equal-in-any-order'); | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| import {LocationManager} from '../../../../../src/backend/model/database/LocationManager'; | ||||
| import {SearchManager} from '../../../../../src/backend/model/database/sql/SearchManager'; | ||||
| import {SearchManager} from '../../../../../src/backend/model/database/SearchManager'; | ||||
| import {SearchResultDTO} from '../../../../../src/common/entities/SearchResultDTO'; | ||||
| import {Utils} from '../../../../../src/common/Utils'; | ||||
| import {DBTestHelper} from '../../../DBTestHelper'; | ||||
| @@ -21,11 +21,11 @@ import { | ||||
|   TextSearchQueryMatchTypes, | ||||
|   ToDateSearch | ||||
| } from '../../../../../src/common/entities/SearchQueryDTO'; | ||||
| import {IndexingManager} from '../../../../../src/backend/model/database/sql/IndexingManager'; | ||||
| import {IndexingManager} from '../../../../../src/backend/model/database/IndexingManager'; | ||||
| import {DirectoryBaseDTO, ParentDirectoryDTO, SubDirectoryDTO} from '../../../../../src/common/entities/DirectoryDTO'; | ||||
| import {TestHelper} from '../../../../TestHelper'; | ||||
| import {ObjectManagers} from '../../../../../src/backend/model/ObjectManagers'; | ||||
| import {GalleryManager} from '../../../../../src/backend/model/database/sql/GalleryManager'; | ||||
| import {GalleryManager} from '../../../../../src/backend/model/database/GalleryManager'; | ||||
| import {Connection} from 'typeorm'; | ||||
| import {GPSMetadata, PhotoDTO, PhotoMetadata} from '../../../../../src/common/entities/PhotoDTO'; | ||||
| import {VideoDTO} from '../../../../../src/common/entities/VideoDTO'; | ||||
|   | ||||
| @@ -1,8 +1,8 @@ | ||||
| import {expect} from 'chai'; | ||||
| import {SQLConnection} from '../../../../../src/backend/model/database/sql/SQLConnection'; | ||||
| import {SharingManager} from '../../../../../src/backend/model/database/sql/SharingManager'; | ||||
| import {SQLConnection} from '../../../../../src/backend/model/database/SQLConnection'; | ||||
| import {SharingManager} from '../../../../../src/backend/model/database/SharingManager'; | ||||
| import {SharingDTO} from '../../../../../src/common/entities/SharingDTO'; | ||||
| import {UserEntity} from '../../../../../src/backend/model/database/sql/enitites/UserEntity'; | ||||
| import {UserEntity} from '../../../../../src/backend/model/database/enitites/UserEntity'; | ||||
| import {UserDTO, UserRoles} from '../../../../../src/common/entities/UserDTO'; | ||||
| import {DBTestHelper} from '../../../DBTestHelper'; | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user