1
0
mirror of https://github.com/xuthus83/pigallery2.git synced 2025-01-14 14:43:17 +08:00

implementing video settings saving

refactoring settings
This commit is contained in:
Patrik J. Braun 2019-12-10 09:36:14 +01:00
parent 41a51e79a9
commit 1be392e7da
49 changed files with 553 additions and 504 deletions

View File

@ -1,11 +1,11 @@
import * as winston from 'winston';
import {Config} from '../common/config/private/Config';
import {LogLevel} from '../common/config/private/IPrivateConfig';
import {ServerConfig} from '../common/config/private/IPrivateConfig';
export const winstonSettings = {
transports: [
new winston.transports.Console(<any>{
level: LogLevel[Config.Server.Log.level],
level: ServerConfig.LogLevel[Config.Server.Log.level],
handleExceptions: true,
json: false,
colorize: true,

View File

@ -1,5 +1,4 @@
import * as path from 'path';
import * as os from 'os';
import * as fs from 'fs';
import * as util from 'util';
import {ITaskExecuter, TaskExecuter} from '../model/threading/TaskExecuter';
@ -12,7 +11,7 @@ const existPr = util.promisify(fs.exists);
export class VideoConverterMWs {
private static taskQue: ITaskExecuter<VideoConverterInput, void> =
new TaskExecuter(Math.max(1, os.cpus().length - 1), (input => VideoConverterWorker.convert(input)));
new TaskExecuter(1, (input => VideoConverterWorker.convert(input)));
public static generateConvertedFileName(videoPath: string): string {

View File

@ -0,0 +1,105 @@
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/sql/IGalleryManager';
import {ServerConfig} from '../../../common/config/private/IPrivateConfig';
const LOG_TAG = '[AdminMWs]';
export class AdminMWs {
public static async loadStatistic(req: Request, res: Response, next: NextFunction) {
if (Config.Server.Database.type === ServerConfig.DatabaseType.memory) {
return next(new ErrorDTO(ErrorCodes.GENERAL_ERROR, 'Statistic is only available for indexed content'));
}
const galleryManager = <ISQLGalleryManager>ObjectManagers.getInstance().GalleryManager;
try {
req.resultPipe = {
directories: await galleryManager.countDirectories(),
photos: await galleryManager.countPhotos(),
videos: await galleryManager.countVideos(),
diskUsage: await galleryManager.countMediaSize(),
};
return next();
} catch (err) {
if (err instanceof Error) {
return next(new ErrorDTO(ErrorCodes.GENERAL_ERROR, 'Error while getting statistic: ' + err.toString(), err));
}
return next(new ErrorDTO(ErrorCodes.GENERAL_ERROR, 'Error while getting statistic', err));
}
}
public static async getDuplicates(req: Request, res: Response, next: NextFunction) {
if (Config.Server.Database.type === ServerConfig.DatabaseType.memory) {
return next(new ErrorDTO(ErrorCodes.GENERAL_ERROR, 'Statistic is only available for indexed content'));
}
const galleryManager = <ISQLGalleryManager>ObjectManagers.getInstance().GalleryManager;
try {
req.resultPipe = await galleryManager.getPossibleDuplicates();
return next();
} catch (err) {
if (err instanceof Error) {
return next(new ErrorDTO(ErrorCodes.GENERAL_ERROR, 'Error while getting duplicates: ' + err.toString(), err));
}
return next(new ErrorDTO(ErrorCodes.GENERAL_ERROR, 'Error while getting duplicates', err));
}
}
public static startTask(req: Request, res: Response, next: NextFunction) {
try {
const id = req.params.id;
const taskConfig: any = req.body.config;
ObjectManagers.getInstance().TaskManager.run(id, taskConfig);
req.resultPipe = 'ok';
return next();
} catch (err) {
if (err instanceof Error) {
return next(new ErrorDTO(ErrorCodes.TASK_ERROR, 'Task error: ' + err.toString(), err));
}
return next(new ErrorDTO(ErrorCodes.TASK_ERROR, 'Task error: ' + JSON.stringify(err, null, ' '), err));
}
}
public static stopTask(req: Request, res: Response, next: NextFunction) {
try {
const id = req.params.id;
ObjectManagers.getInstance().TaskManager.stop(id);
req.resultPipe = 'ok';
return next();
} catch (err) {
if (err instanceof Error) {
return next(new ErrorDTO(ErrorCodes.TASK_ERROR, 'Task error: ' + err.toString(), err));
}
return next(new ErrorDTO(ErrorCodes.TASK_ERROR, 'Task error: ' + JSON.stringify(err, null, ' '), err));
}
}
public static getAvailableTasks(req: Request, res: Response, next: NextFunction) {
try {
req.resultPipe = ObjectManagers.getInstance().TaskManager.getAvailableTasks();
return next();
} catch (err) {
if (err instanceof Error) {
return next(new ErrorDTO(ErrorCodes.TASK_ERROR, 'Task error: ' + err.toString(), err));
}
return next(new ErrorDTO(ErrorCodes.TASK_ERROR, 'Task error: ' + JSON.stringify(err, null, ' '), err));
}
}
public static getTaskProgresses(req: Request, res: Response, next: NextFunction) {
try {
req.resultPipe = ObjectManagers.getInstance().TaskManager.getProgresses();
return next();
} catch (err) {
if (err instanceof Error) {
return next(new ErrorDTO(ErrorCodes.TASK_ERROR, 'Task error: ' + err.toString(), err));
}
return next(new ErrorDTO(ErrorCodes.TASK_ERROR, 'Task error: ' + JSON.stringify(err, null, ' '), err));
}
}
}

View File

@ -1,64 +1,21 @@
/**/
import {NextFunction, Request, Response} from 'express';
import {ErrorCodes, ErrorDTO} from '../../common/entities/Error';
import {ObjectManagers} from '../model/ObjectManagers';
import {Logger} from '../Logger';
import {SQLConnection} from '../model/sql/SQLConnection';
import {DataBaseConfig, DatabaseType, IndexingConfig, TaskConfig, ThumbnailConfig} from '../../common/config/private/IPrivateConfig';
import {Config} from '../../common/config/private/Config';
import {ConfigDiagnostics} from '../model/diagnostics/ConfigDiagnostics';
import {ClientConfig} from '../../common/config/public/ConfigClass';
import {BasicConfigDTO} from '../../common/entities/settings/BasicConfigDTO';
import {OtherConfigDTO} from '../../common/entities/settings/OtherConfigDTO';
import {ProjectPath} from '../ProjectPath';
import {PrivateConfigClass} from '../../common/config/private/PrivateConfigClass';
import {ISQLGalleryManager} from '../model/sql/IGalleryManager';
import {ErrorCodes, ErrorDTO} from '../../../common/entities/Error';
import {ObjectManagers} from '../../model/ObjectManagers';
import {Logger} from '../../Logger';
import {SQLConnection} from '../../model/sql/SQLConnection';
import {Config} from '../../../common/config/private/Config';
import {ConfigDiagnostics} from '../../model/diagnostics/ConfigDiagnostics';
import {ClientConfig} from '../../../common/config/public/ConfigClass';
import {BasicConfigDTO} from '../../../common/entities/settings/BasicConfigDTO';
import {OtherConfigDTO} from '../../../common/entities/settings/OtherConfigDTO';
import {ProjectPath} from '../../ProjectPath';
import {PrivateConfigClass} from '../../../common/config/private/PrivateConfigClass';
import {ServerConfig} from '../../../common/config/private/IPrivateConfig';
const LOG_TAG = '[AdminMWs]';
const LOG_TAG = '[SettingsMWs]';
export class AdminMWs {
public static async loadStatistic(req: Request, res: Response, next: NextFunction) {
if (Config.Server.Database.type === DatabaseType.memory) {
return next(new ErrorDTO(ErrorCodes.GENERAL_ERROR, 'Statistic is only available for indexed content'));
}
const galleryManager = <ISQLGalleryManager>ObjectManagers.getInstance().GalleryManager;
try {
req.resultPipe = {
directories: await galleryManager.countDirectories(),
photos: await galleryManager.countPhotos(),
videos: await galleryManager.countVideos(),
diskUsage: await galleryManager.countMediaSize(),
};
return next();
} catch (err) {
if (err instanceof Error) {
return next(new ErrorDTO(ErrorCodes.GENERAL_ERROR, 'Error while getting statistic: ' + err.toString(), err));
}
return next(new ErrorDTO(ErrorCodes.GENERAL_ERROR, 'Error while getting statistic', err));
}
}
public static async getDuplicates(req: Request, res: Response, next: NextFunction) {
if (Config.Server.Database.type === DatabaseType.memory) {
return next(new ErrorDTO(ErrorCodes.GENERAL_ERROR, 'Statistic is only available for indexed content'));
}
const galleryManager = <ISQLGalleryManager>ObjectManagers.getInstance().GalleryManager;
try {
req.resultPipe = await galleryManager.getPossibleDuplicates();
return next();
} catch (err) {
if (err instanceof Error) {
return next(new ErrorDTO(ErrorCodes.GENERAL_ERROR, 'Error while getting duplicates: ' + err.toString(), err));
}
return next(new ErrorDTO(ErrorCodes.GENERAL_ERROR, 'Error while getting duplicates', err));
}
}
export class SettingsMWs {
public static async updateDatabaseSettings(req: Request, res: Response, next: NextFunction) {
@ -66,17 +23,17 @@ export class AdminMWs {
return next(new ErrorDTO(ErrorCodes.INPUT_ERROR, 'settings is needed'));
}
const databaseSettings = <DataBaseConfig>req.body.settings;
const databaseSettings = <ServerConfig.DataBaseConfig>req.body.settings;
try {
if (databaseSettings.type !== DatabaseType.memory) {
if (databaseSettings.type !== ServerConfig.DatabaseType.memory) {
await SQLConnection.tryConnection(databaseSettings);
}
Config.Server.Database = databaseSettings;
// only updating explicitly set config (not saving config set by the diagnostics)
const original = Config.original();
original.Server.Database = databaseSettings;
if (databaseSettings.type === DatabaseType.memory) {
if (databaseSettings.type === ServerConfig.DatabaseType.memory) {
original.Client.Sharing.enabled = false;
original.Client.Search.enabled = false;
}
@ -86,7 +43,7 @@ export class AdminMWs {
Logger.info(LOG_TAG, JSON.stringify(Config, null, '\t'));
await ObjectManagers.reset();
if (Config.Server.Database.type !== DatabaseType.memory) {
if (Config.Server.Database.type !== ServerConfig.DatabaseType.memory) {
await ObjectManagers.InitSQLManagers();
} else {
await ObjectManagers.InitMemoryManagers();
@ -132,12 +89,20 @@ export class AdminMWs {
}
try {
await ConfigDiagnostics.testVideoConfig(<ClientConfig.VideoConfig>req.body.settings);
const settings: {
server: ServerConfig.VideoConfig,
client: ClientConfig.VideoConfig
} = req.body.settings;
Config.Client.Video = <ClientConfig.VideoConfig>req.body.settings;
// only updating explicitly set config (not saving config set by the diagnostics)
const original = Config.original();
original.Client.Video = <ClientConfig.VideoConfig>req.body.settings;
await ConfigDiagnostics.testClientVideoConfig(settings.client);
await ConfigDiagnostics.testServerVideoConfig(settings.server, original);
Config.Server.Video = settings.server;
Config.Client.Video = settings.client;
// only updating explicitly set config (not saving config set by the diagnostics)
original.Server.Video = settings.server;
original.Client.Video = settings.client;
original.save();
await ConfigDiagnostics.runDiagnostics();
Logger.info(LOG_TAG, 'new config:');
@ -202,7 +167,6 @@ export class AdminMWs {
}
}
public static async updateRandomPhotoSettings(req: Request, res: Response, next: NextFunction) {
if ((typeof req.body === 'undefined') || (typeof req.body.settings === 'undefined')) {
return next(new ErrorDTO(ErrorCodes.INPUT_ERROR, 'settings is needed'));
@ -278,7 +242,6 @@ export class AdminMWs {
}
}
public static async updateAuthenticationSettings(req: Request, res: Response, next: NextFunction) {
if ((typeof req.body === 'undefined') || (typeof req.body.settings === 'undefined')) {
return next(new ErrorDTO(ErrorCodes.INPUT_ERROR, 'settings is needed'));
@ -312,7 +275,7 @@ export class AdminMWs {
try {
const settings: {
server: ThumbnailConfig,
server: ServerConfig.ThumbnailConfig,
client: ClientConfig.ThumbnailConfig
} = req.body.settings;
@ -338,7 +301,6 @@ export class AdminMWs {
}
}
public static async updateBasicSettings(req: Request, res: Response, next: NextFunction) {
if ((typeof req.body === 'undefined') || (typeof req.body.settings === 'undefined')) {
return next(new ErrorDTO(ErrorCodes.INPUT_ERROR, 'settings is needed'));
@ -375,7 +337,6 @@ export class AdminMWs {
}
}
public static async updateOtherSettings(req: Request, res: Response, next: NextFunction) {
if ((typeof req.body === 'undefined') || (typeof req.body.settings === 'undefined')) {
return next(new ErrorDTO(ErrorCodes.INPUT_ERROR, 'settings is needed'));
@ -419,7 +380,7 @@ export class AdminMWs {
}
try {
const settings: IndexingConfig = req.body.settings;
const settings: ServerConfig.IndexingConfig = req.body.settings;
Config.Server.Indexing = settings;
// only updating explicitly set config (not saving config set by the diagnostics)
@ -438,7 +399,6 @@ export class AdminMWs {
}
}
public static async updateTasksSettings(req: Request, res: Response, next: NextFunction) {
if ((typeof req.body === 'undefined') || (typeof req.body.settings === 'undefined')) {
return next(new ErrorDTO(ErrorCodes.INPUT_ERROR, 'settings is needed'));
@ -447,7 +407,7 @@ export class AdminMWs {
try {
// only updating explicitly set config (not saving config set by the diagnostics)
const settings: TaskConfig = req.body.settings;
const settings: ServerConfig.TaskConfig = req.body.settings;
const original = Config.original();
await ConfigDiagnostics.testTasksConfig(settings, original);
@ -468,58 +428,4 @@ export class AdminMWs {
}
}
public static startTask(req: Request, res: Response, next: NextFunction) {
try {
const id = req.params.id;
const taskConfig: any = req.body.config;
ObjectManagers.getInstance().TaskManager.run(id, taskConfig);
req.resultPipe = 'ok';
return next();
} catch (err) {
if (err instanceof Error) {
return next(new ErrorDTO(ErrorCodes.TASK_ERROR, 'Task error: ' + err.toString(), err));
}
return next(new ErrorDTO(ErrorCodes.TASK_ERROR, 'Task error: ' + JSON.stringify(err, null, ' '), err));
}
}
public static stopTask(req: Request, res: Response, next: NextFunction) {
try {
const id = req.params.id;
ObjectManagers.getInstance().TaskManager.stop(id);
req.resultPipe = 'ok';
return next();
} catch (err) {
if (err instanceof Error) {
return next(new ErrorDTO(ErrorCodes.TASK_ERROR, 'Task error: ' + err.toString(), err));
}
return next(new ErrorDTO(ErrorCodes.TASK_ERROR, 'Task error: ' + JSON.stringify(err, null, ' '), err));
}
}
public static getAvailableTasks(req: Request, res: Response, next: NextFunction) {
try {
req.resultPipe = ObjectManagers.getInstance().TaskManager.getAvailableTasks();
return next();
} catch (err) {
if (err instanceof Error) {
return next(new ErrorDTO(ErrorCodes.TASK_ERROR, 'Task error: ' + err.toString(), err));
}
return next(new ErrorDTO(ErrorCodes.TASK_ERROR, 'Task error: ' + JSON.stringify(err, null, ' '), err));
}
}
public static getTaskProgresses(req: Request, res: Response, next: NextFunction) {
try {
req.resultPipe = ObjectManagers.getInstance().TaskManager.getProgresses();
return next();
} catch (err) {
if (err instanceof Error) {
return next(new ErrorDTO(ErrorCodes.TASK_ERROR, 'Task error: ' + err.toString(), err));
}
return next(new ErrorDTO(ErrorCodes.TASK_ERROR, 'Task error: ' + JSON.stringify(err, null, ' '), err));
}
}
}

View File

@ -8,13 +8,13 @@ import {ContentWrapper} from '../../../common/entities/ConentWrapper';
import {DirectoryDTO} from '../../../common/entities/DirectoryDTO';
import {ProjectPath} from '../../ProjectPath';
import {Config} from '../../../common/config/private/Config';
import {ThumbnailProcessingLib} from '../../../common/config/private/IPrivateConfig';
import {ThumbnailTH} from '../../model/threading/ThreadPool';
import {RendererInput, ThumbnailSourceType, ThumbnailWorker} from '../../model/threading/ThumbnailWorker';
import {MediaDTO} from '../../../common/entities/MediaDTO';
import {ITaskExecuter, TaskExecuter} from '../../model/threading/TaskExecuter';
import {FaceRegion, PhotoDTO} from '../../../common/entities/PhotoDTO';
import {PersonWithPhoto} from '../PersonMWs';
import {ServerConfig} from '../../../common/config/private/IPrivateConfig';
export class ThumbnailGeneratorMWs {
@ -38,7 +38,7 @@ export class ThumbnailGeneratorMWs {
}
if (Config.Server.Threading.enable === true &&
Config.Server.Thumbnail.processingLibrary === ThumbnailProcessingLib.Jimp) {
Config.Server.Thumbnail.processingLibrary === ServerConfig.ThumbnailProcessingLib.Jimp) {
this.taskQue = new ThumbnailTH(Config.Client.Thumbnail.concurrentThumbnailGenerations);
} else {
this.taskQue = new TaskExecuter(Config.Client.Thumbnail.concurrentThumbnailGenerations,

View File

@ -1,12 +1,4 @@
import {Config} from '../../../common/config/private/Config';
import {
DataBaseConfig,
DatabaseType,
IPrivateConfig,
TaskConfig,
ThumbnailConfig,
ThumbnailProcessingLib
} from '../../../common/config/private/IPrivateConfig';
import {Logger} from '../../Logger';
import {NotificationManager} from '../NotifocationManager';
import {ProjectPath} from '../../ProjectPath';
@ -14,21 +6,20 @@ import {SQLConnection} from '../sql/SQLConnection';
import * as fs from 'fs';
import {ClientConfig} from '../../../common/config/public/ConfigClass';
import {FFmpegFactory} from '../FFmpegFactory';
import VideoConfig = ClientConfig.VideoConfig;
import MetaFileConfig = ClientConfig.MetaFileConfig;
import {IPrivateConfig, ServerConfig} from '../../../common/config/private/IPrivateConfig';
const LOG_TAG = '[ConfigDiagnostics]';
export class ConfigDiagnostics {
static async testDatabase(databaseConfig: DataBaseConfig) {
if (databaseConfig.type !== DatabaseType.memory) {
static async testDatabase(databaseConfig: ServerConfig.DataBaseConfig) {
if (databaseConfig.type !== ServerConfig.DatabaseType.memory) {
await SQLConnection.tryConnection(databaseConfig);
}
}
static async testMetaFileConfig(metaFileConfig: MetaFileConfig, config: IPrivateConfig) {
static async testMetaFileConfig(metaFileConfig: ClientConfig.MetaFileConfig, config: IPrivateConfig) {
if (metaFileConfig.enabled === true &&
config.Client.Map.enabled === false) {
throw new Error('*.gpx meta files are not supported without MAP');
@ -36,7 +27,7 @@ export class ConfigDiagnostics {
}
static testVideoConfig(videoConfig: VideoConfig) {
static testClientVideoConfig(videoConfig: ClientConfig.VideoConfig) {
return new Promise((resolve, reject) => {
try {
if (videoConfig.enabled === true) {
@ -61,13 +52,21 @@ export class ConfigDiagnostics {
});
}
static async testThumbnailLib(processingLibrary: ThumbnailProcessingLib) {
static async testServerVideoConfig(videoConfig: ServerConfig.VideoConfig, config: IPrivateConfig) {
if (config.Client.Video.enabled === true) {
if (videoConfig.transcoding.fps <= 0) {
throw new Error('fps should be grater than 0');
}
}
}
static async testThumbnailLib(processingLibrary: ServerConfig.ThumbnailProcessingLib) {
switch (processingLibrary) {
case ThumbnailProcessingLib.sharp:
case ServerConfig.ThumbnailProcessingLib.sharp:
const sharp = require('sharp');
sharp();
break;
case ThumbnailProcessingLib.gm:
case ServerConfig.ThumbnailProcessingLib.gm:
const gm = require('gm');
await new Promise((resolve, reject) => {
gm(ProjectPath.FrontendFolder + '/assets/icon.png').size((err: Error) => {
@ -107,7 +106,7 @@ export class ConfigDiagnostics {
}
static async testServerThumbnailConfig(thumbnailConfig: ThumbnailConfig) {
static async testServerThumbnailConfig(thumbnailConfig: ServerConfig.ThumbnailConfig) {
await ConfigDiagnostics.testThumbnailLib(thumbnailConfig.processingLibrary);
await ConfigDiagnostics.testThumbnailFolder(thumbnailConfig.folder);
}
@ -128,13 +127,13 @@ export class ConfigDiagnostics {
}
static async testTasksConfig(faces: TaskConfig, config: IPrivateConfig) {
static async testTasksConfig(faces: ServerConfig.TaskConfig, config: IPrivateConfig) {
}
static async testFacesConfig(faces: ClientConfig.FacesConfig, config: IPrivateConfig) {
if (faces.enabled === true) {
if (config.Server.Database.type === DatabaseType.memory) {
if (config.Server.Database.type === ServerConfig.DatabaseType.memory) {
throw new Error('Memory Database do not support faces');
}
if (config.Client.Search.enabled === false) {
@ -145,7 +144,7 @@ export class ConfigDiagnostics {
static async testSearchConfig(search: ClientConfig.SearchConfig, config: IPrivateConfig) {
if (search.enabled === true &&
config.Server.Database.type === DatabaseType.memory) {
config.Server.Database.type === ServerConfig.DatabaseType.memory) {
throw new Error('Memory Database do not support searching');
}
}
@ -153,7 +152,7 @@ export class ConfigDiagnostics {
static async testSharingConfig(sharing: ClientConfig.SharingConfig, config: IPrivateConfig) {
if (sharing.enabled === true &&
config.Server.Database.type === DatabaseType.memory) {
config.Server.Database.type === ServerConfig.DatabaseType.memory) {
throw new Error('Memory Database do not support sharing');
}
if (sharing.enabled === true &&
@ -164,8 +163,8 @@ export class ConfigDiagnostics {
static async testRandomPhotoConfig(sharing: ClientConfig.RandomPhotoConfig, config: IPrivateConfig) {
if (sharing.enabled === true &&
config.Server.Database.type === DatabaseType.memory) {
throw new Error('Memory Database do not support sharing');
config.Server.Database.type === ServerConfig.DatabaseType.memory) {
throw new Error('Memory Database do not support random photo');
}
}
@ -194,7 +193,7 @@ export class ConfigDiagnostics {
static async runDiagnostics() {
if (Config.Server.Database.type !== DatabaseType.memory) {
if (Config.Server.Database.type !== ServerConfig.DatabaseType.memory) {
try {
await ConfigDiagnostics.testDatabase(Config.Server.Database);
} catch (ex) {
@ -202,23 +201,23 @@ export class ConfigDiagnostics {
Logger.warn(LOG_TAG, '[SQL error]', err.toString());
Logger.warn(LOG_TAG, 'Error during initializing SQL falling back temporally to memory DB');
NotificationManager.warning('Error during initializing SQL falling back temporally to memory DB', err.toString());
Config.setDatabaseType(DatabaseType.memory);
Config.setDatabaseType(ServerConfig.DatabaseType.memory);
}
}
if (Config.Server.Thumbnail.processingLibrary !== ThumbnailProcessingLib.Jimp) {
if (Config.Server.Thumbnail.processingLibrary !== ServerConfig.ThumbnailProcessingLib.Jimp) {
try {
await ConfigDiagnostics.testThumbnailLib(Config.Server.Thumbnail.processingLibrary);
} catch (ex) {
const err: Error = ex;
NotificationManager.warning('Thumbnail hardware acceleration is not possible.' +
' \'' + ThumbnailProcessingLib[Config.Server.Thumbnail.processingLibrary] + '\' node module is not found.' +
' \'' + ServerConfig.ThumbnailProcessingLib[Config.Server.Thumbnail.processingLibrary] + '\' node module is not found.' +
' Falling back temporally to JS based thumbnail generation', err.toString());
Logger.warn(LOG_TAG, '[Thumbnail hardware acceleration] module error: ', err.toString());
Logger.warn(LOG_TAG, 'Thumbnail hardware acceleration is not possible.' +
' \'' + ThumbnailProcessingLib[Config.Server.Thumbnail.processingLibrary] + '\' node module is not found.' +
' \'' + ServerConfig.ThumbnailProcessingLib[Config.Server.Thumbnail.processingLibrary] + '\' node module is not found.' +
' Falling back temporally to JS based thumbnail generation');
Config.Server.Thumbnail.processingLibrary = ThumbnailProcessingLib.Jimp;
Config.Server.Thumbnail.processingLibrary = ServerConfig.ThumbnailProcessingLib.Jimp;
}
}
@ -232,7 +231,8 @@ export class ConfigDiagnostics {
try {
await ConfigDiagnostics.testVideoConfig(Config.Client.Video);
await ConfigDiagnostics.testClientVideoConfig(Config.Server.Video);
await ConfigDiagnostics.testServerVideoConfig(Config.Server.Video, Config);
} catch (ex) {
const err: Error = ex;
NotificationManager.warning('Video support error, switching off..', err.toString());

View File

@ -5,9 +5,9 @@ import * as fs from 'fs';
import {DiskManager} from '../DiskManger';
import {ProjectPath} from '../../ProjectPath';
import {Config} from '../../../common/config/private/Config';
import {ReIndexingSensitivity} from '../../../common/config/private/IPrivateConfig';
import {PhotoDTO} from '../../../common/entities/PhotoDTO';
import {DiskMangerWorker} from '../threading/DiskMangerWorker';
import {ServerConfig} from '../../../common/config/private/IPrivateConfig';
export class GalleryManager implements IGalleryManager {
@ -18,7 +18,7 @@ export class GalleryManager implements IGalleryManager {
const lastModified = DiskMangerWorker.calcLastModified(stat);
if (Date.now() - knownLastScanned <= Config.Server.Indexing.cachedFolderTimeout &&
lastModified === knownLastModified &&
Config.Server.Indexing.reIndexingSensitivity < ReIndexingSensitivity.high) {
Config.Server.Indexing.reIndexingSensitivity < ServerConfig.ReIndexingSensitivity.high) {
return Promise.resolve(null);
}
}

View File

@ -8,10 +8,9 @@ import {PhotoEntity} from './enitites/PhotoEntity';
import {ProjectPath} from '../../ProjectPath';
import {Config} from '../../../common/config/private/Config';
import {ISQLGalleryManager} from './IGalleryManager';
import {DatabaseType, ReIndexingSensitivity} from '../../../common/config/private/IPrivateConfig';
import {PhotoDTO} from '../../../common/entities/PhotoDTO';
import {OrientationType} from '../../../common/entities/RandomQueryDTO';
import {Brackets, Connection} from 'typeorm';
import {Brackets, Connection, SelectQueryBuilder} from 'typeorm';
import {MediaEntity} from './enitites/MediaEntity';
import {VideoEntity} from './enitites/VideoEntity';
import {DiskMangerWorker} from '../threading/DiskMangerWorker';
@ -19,6 +18,7 @@ import {Logger} from '../../Logger';
import {FaceRegionEntry} from './enitites/FaceRegionEntry';
import {ObjectManagers} from '../ObjectManagers';
import {DuplicatesDTO} from '../../../common/entities/DuplicatesDTO';
import {ServerConfig} from '../../../common/config/private/IPrivateConfig';
const LOG_TAG = '[GalleryManager]';
@ -43,11 +43,11 @@ export class GalleryManager implements IGalleryManager, ISQLGalleryManager {
if (knownLastModified && knownLastScanned
&& lastModified === knownLastModified &&
dir.lastScanned === knownLastScanned) {
if (Config.Server.Indexing.reIndexingSensitivity === ReIndexingSensitivity.low) {
if (Config.Server.Indexing.reIndexingSensitivity === ServerConfig.ReIndexingSensitivity.low) {
return null;
}
if (Date.now() - dir.lastScanned <= Config.Server.Indexing.cachedFolderTimeout &&
Config.Server.Indexing.reIndexingSensitivity === ReIndexingSensitivity.medium) {
Config.Server.Indexing.reIndexingSensitivity === ServerConfig.ReIndexingSensitivity.medium) {
return null;
}
}
@ -62,8 +62,8 @@ export class GalleryManager implements IGalleryManager, ISQLGalleryManager {
// not indexed since a while, index it in a lazy manner
if ((Date.now() - dir.lastScanned > Config.Server.Indexing.cachedFolderTimeout &&
Config.Server.Indexing.reIndexingSensitivity >= ReIndexingSensitivity.medium) ||
Config.Server.Indexing.reIndexingSensitivity >= ReIndexingSensitivity.high) {
Config.Server.Indexing.reIndexingSensitivity >= ServerConfig.ReIndexingSensitivity.medium) ||
Config.Server.Indexing.reIndexingSensitivity >= ServerConfig.ReIndexingSensitivity.high) {
// on the fly reindexing
Logger.silly(LOG_TAG, 'lazy reindexing reason: cache timeout: lastScanned: '
@ -86,7 +86,7 @@ export class GalleryManager implements IGalleryManager, ISQLGalleryManager {
public async getRandomPhoto(queryFilter: RandomQuery): Promise<PhotoDTO> {
const connection = await SQLConnection.getConnection();
const photosRepository = connection.getRepository(PhotoEntity);
const query = photosRepository.createQueryBuilder('photo');
const query: SelectQueryBuilder<PhotoEntity> = photosRepository.createQueryBuilder('photo');
query.innerJoinAndSelect('photo.directory', 'directory');
if (queryFilter.directory) {
@ -133,7 +133,7 @@ export class GalleryManager implements IGalleryManager, ISQLGalleryManager {
query.andWhere('photo.metadata.size.width <= photo.metadata.size.height');
}
if (Config.Server.Database.type === DatabaseType.mysql) {
if (Config.Server.Database.type === ServerConfig.DatabaseType.mysql) {
return await query.groupBy('RAND(), photo.id').limit(1).getOne();
}
return await query.groupBy('RANDOM()').limit(1).getOne();

View File

@ -6,7 +6,6 @@ import {PhotoEntity} from './enitites/PhotoEntity';
import {DirectoryEntity} from './enitites/DirectoryEntity';
import {Config} from '../../../common/config/private/Config';
import {SharingEntity} from './enitites/SharingEntity';
import {DataBaseConfig, DatabaseType, SQLLogLevel} from '../../../common/config/private/IPrivateConfig';
import {PasswordHelper} from '../PasswordHelper';
import {ProjectPath} from '../../ProjectPath';
import {VersionEntity} from './enitites/VersionEntity';
@ -18,6 +17,7 @@ import {FileEntity} from './enitites/FileEntity';
import {FaceRegionEntry} from './enitites/FaceRegionEntry';
import {PersonEntry} from './enitites/PersonEntry';
import {Utils} from '../../../common/Utils';
import {ServerConfig} from '../../../common/config/private/IPrivateConfig';
export class SQLConnection {
@ -45,8 +45,8 @@ export class SQLConnection {
VersionEntity
];
options.synchronize = false;
if (Config.Server.Log.sqlLevel !== SQLLogLevel.none) {
options.logging = SQLLogLevel[Config.Server.Log.sqlLevel];
if (Config.Server.Log.sqlLevel !== ServerConfig.SQLLogLevel.none) {
options.logging = ServerConfig.SQLLogLevel[Config.Server.Log.sqlLevel];
}
this.connection = await this.createConnection(options);
@ -55,7 +55,7 @@ export class SQLConnection {
return this.connection;
}
public static async tryConnection(config: DataBaseConfig) {
public static async tryConnection(config: ServerConfig.DataBaseConfig) {
try {
await getConnection('test').close();
} catch (err) {
@ -75,8 +75,8 @@ export class SQLConnection {
VersionEntity
];
options.synchronize = false;
if (Config.Server.Log.sqlLevel !== SQLLogLevel.none) {
options.logging = SQLLogLevel[Config.Server.Log.sqlLevel];
if (Config.Server.Log.sqlLevel !== ServerConfig.SQLLogLevel.none) {
options.logging = ServerConfig.SQLLogLevel[Config.Server.Log.sqlLevel];
}
const conn = await this.createConnection(options);
await SQLConnection.schemeSync(conn);
@ -163,9 +163,9 @@ export class SQLConnection {
}
}
private static getDriver(config: DataBaseConfig): ConnectionOptions {
private static getDriver(config: ServerConfig.DataBaseConfig): ConnectionOptions {
let driver: ConnectionOptions = null;
if (config.type === DatabaseType.mysql) {
if (config.type === ServerConfig.DatabaseType.mysql) {
driver = {
type: 'mysql',
host: config.mysql.host,
@ -175,7 +175,7 @@ export class SQLConnection {
database: config.mysql.database,
charset: 'utf8'
};
} else if (config.type === DatabaseType.sqlite) {
} else if (config.type === ServerConfig.DatabaseType.sqlite) {
driver = {
type: 'sqlite',
database: ProjectPath.getAbsolutePath(config.sqlite.storage)

View File

@ -1,15 +1,15 @@
import {Config} from '../../../../common/config/private/Config';
import {DatabaseType} from '../../../../common/config/private/IPrivateConfig';
import {ServerConfig} from '../../../../common/config/private/IPrivateConfig';
import {ColumnOptions} from 'typeorm/decorator/options/ColumnOptions';
export class ColumnCharsetCS implements ColumnOptions {
public get charset(): string {
return Config.Server.Database.type === DatabaseType.mysql ? 'utf8' : null;
return Config.Server.Database.type === ServerConfig.DatabaseType.mysql ? 'utf8' : null;
}
public get collation(): string {
return Config.Server.Database.type === DatabaseType.mysql ? 'utf8_bin' : null;
return Config.Server.Database.type === ServerConfig.DatabaseType.mysql ? 'utf8_bin' : null;
}
}

View File

@ -4,8 +4,6 @@ import {MediaDimension, MediaDTO, MediaMetadata} from '../../../../common/entiti
import {OrientationTypes} from 'ts-exif-parser';
import {CameraMetadataEntity, PositionMetaDataEntity} from './PhotoEntity';
import {FaceRegionEntry} from './FaceRegionEntry';
import {Config} from '../../../../common/config/private/Config';
import {DatabaseType} from '../../../../common/config/private/IPrivateConfig';
import {columnCharsetCS} from './EntityUtils';
export class MediaDimensionEntity implements MediaDimension {
@ -59,7 +57,6 @@ export class MediaMetadataEntity implements MediaMetadata {
}
// TODO: fix inheritance once its working in typeorm
@Entity()
@Unique(['name', 'directory'])

View File

@ -1,9 +1,9 @@
import {TaskProgressDTO} from '../../../../common/entities/settings/TaskProgressDTO';
import {ObjectManagers} from '../../ObjectManagers';
import {Config} from '../../../../common/config/private/Config';
import {DatabaseType} from '../../../../common/config/private/IPrivateConfig';
import {ConfigTemplateEntry, DefaultsTasks} from '../../../../common/entities/task/TaskDTO';
import {Task} from './Task';
import {ServerConfig} from '../../../../common/config/private/IPrivateConfig';
const LOG_TAG = '[DBRestTask]';
@ -12,7 +12,7 @@ export class DBRestTask extends Task {
public readonly ConfigTemplate: ConfigTemplateEntry[] = null;
public get Supported(): boolean {
return Config.Server.Database.type !== DatabaseType.memory;
return Config.Server.Database.type !== ServerConfig.DatabaseType.memory;
}
protected async init() {

View File

@ -9,8 +9,8 @@ import {MediaDTO} from '../../../../common/entities/MediaDTO';
import {ProjectPath} from '../../../ProjectPath';
import {ThumbnailGeneratorMWs} from '../../../middlewares/thumbnail/ThumbnailGeneratorMWs';
import {Task} from './Task';
import {DatabaseType} from '../../../../common/config/private/IPrivateConfig';
import {ConfigTemplateEntry, DefaultsTasks} from '../../../../common/entities/task/TaskDTO';
import {ServerConfig} from '../../../../common/config/private/IPrivateConfig';
declare const global: any;
const LOG_TAG = '[IndexingTask]';
@ -26,7 +26,7 @@ export class IndexingTask extends Task<{ createThumbnails: boolean }> {
}];
public get Supported(): boolean {
return Config.Server.Database.type !== DatabaseType.memory;
return Config.Server.Database.type !== ServerConfig.DatabaseType.memory;
}
protected async init() {

View File

@ -2,23 +2,23 @@ import {Metadata, Sharp} from 'sharp';
import {Dimensions, State} from 'gm';
import {Logger} from '../../Logger';
import {FfmpegCommand, FfprobeData} from 'fluent-ffmpeg';
import {ThumbnailProcessingLib} from '../../../common/config/private/IPrivateConfig';
import {FFmpegFactory} from '../FFmpegFactory';
import {ServerConfig} from '../../../common/config/private/IPrivateConfig';
export class ThumbnailWorker {
private static imageRenderer: (input: RendererInput) => Promise<void> = null;
private static videoRenderer: (input: RendererInput) => Promise<void> = null;
private static rendererType: ThumbnailProcessingLib = null;
private static rendererType: ServerConfig.ThumbnailProcessingLib = null;
public static render(input: RendererInput, renderer: ThumbnailProcessingLib): Promise<void> {
public static render(input: RendererInput, renderer: ServerConfig.ThumbnailProcessingLib): Promise<void> {
if (input.type === ThumbnailSourceType.Image) {
return this.renderFromImage(input, renderer);
}
return this.renderFromVideo(input);
}
public static renderFromImage(input: RendererInput, renderer: ThumbnailProcessingLib): Promise<void> {
public static renderFromImage(input: RendererInput, renderer: ServerConfig.ThumbnailProcessingLib): Promise<void> {
if (ThumbnailWorker.rendererType !== renderer) {
ThumbnailWorker.imageRenderer = ImageRendererFactory.build(renderer);
ThumbnailWorker.rendererType = renderer;
@ -117,13 +117,13 @@ export class VideoRendererFactory {
export class ImageRendererFactory {
public static build(renderer: ThumbnailProcessingLib): (input: RendererInput) => Promise<void> {
public static build(renderer: ServerConfig.ThumbnailProcessingLib): (input: RendererInput) => Promise<void> {
switch (renderer) {
case ThumbnailProcessingLib.Jimp:
case ServerConfig.ThumbnailProcessingLib.Jimp:
return ImageRendererFactory.Jimp();
case ThumbnailProcessingLib.gm:
case ServerConfig.ThumbnailProcessingLib.gm:
return ImageRendererFactory.Gm();
case ThumbnailProcessingLib.sharp:
case ServerConfig.ThumbnailProcessingLib.sharp:
return ImageRendererFactory.Sharp();
}
throw new Error('unknown renderer');

View File

@ -1,6 +1,7 @@
import {Logger} from '../../Logger';
import {FfmpegCommand} from 'fluent-ffmpeg';
import {FFmpegFactory} from '../FFmpegFactory';
import {ServerConfig} from '../../../common/config/private/IPrivateConfig';
export interface VideoConverterInput {
@ -8,10 +9,10 @@ export interface VideoConverterInput {
output: {
path: string,
bitRate?: number,
resolution?: 240 | 360 | 480 | 720 | 1080 | 1440 | 2160 | 4320,
resolution?: ServerConfig.resolutionType,
fps?: number,
codec: string,
format: string
codec: ServerConfig.codecType,
format: ServerConfig.formatType
};
}

View File

@ -1,9 +1,9 @@
import {DiskMangerWorker} from './DiskMangerWorker';
import {Logger} from '../../Logger';
import {RendererInput, ThumbnailWorker} from './ThumbnailWorker';
import {ThumbnailProcessingLib} from '../../../common/config/private/IPrivateConfig';
import {DirectoryDTO} from '../../../common/entities/DirectoryDTO';
import {Utils} from '../../../common/Utils';
import {ServerConfig} from '../../../common/config/private/IPrivateConfig';
export class Worker {
@ -53,7 +53,7 @@ export interface DiskManagerTask extends WorkerTask {
export interface ThumbnailTask extends WorkerTask {
input: RendererInput;
renderer: ThumbnailProcessingLib;
renderer: ServerConfig.ThumbnailProcessingLib;
}
export module WorkerTask {

28
backend/routes/Router.ts Normal file
View File

@ -0,0 +1,28 @@
import {Express} from 'express';
import {PublicRouter} from './PublicRouter';
import {UserRouter} from './UserRouter';
import {GalleryRouter} from './GalleryRouter';
import {PersonRouter} from './PersonRouter';
import {SharingRouter} from './SharingRouter';
import {AdminRouter} from './admin/AdminRouter';
import {SettingsRouter} from './admin/SettingsRouter';
import {NotificationRouter} from './NotificationRouter';
import {ErrorRouter} from './ErrorRouter';
export class Router {
public static route(app: Express) {
PublicRouter.route(app);
UserRouter.route(app);
GalleryRouter.route(app);
PersonRouter.route(app);
SharingRouter.route(app);
AdminRouter.route(app);
SettingsRouter.route(app);
NotificationRouter.route(app);
ErrorRouter.route(app);
}
}

View File

@ -0,0 +1,61 @@
import {AuthenticationMWs} from '../../middlewares/user/AuthenticationMWs';
import {UserRoles} from '../../../common/entities/UserDTO';
import {RenderingMWs} from '../../middlewares/RenderingMWs';
import {AdminMWs} from '../../middlewares/admin/AdminMWs';
import {Express} from 'express';
export class AdminRouter {
public static route(app: Express) {
this.addGetStatistic(app);
this.addGetDuplicates(app);
this.addTasks(app);
}
private static addGetStatistic(app: Express) {
app.get('/api/admin/statistic',
AuthenticationMWs.authenticate,
AuthenticationMWs.authorise(UserRoles.Admin),
AdminMWs.loadStatistic,
RenderingMWs.renderResult
);
}
private static addGetDuplicates(app: Express) {
app.get('/api/admin/duplicates',
AuthenticationMWs.authenticate,
AuthenticationMWs.authorise(UserRoles.Admin),
AdminMWs.getDuplicates,
RenderingMWs.renderResult
);
}
private static addTasks(app: Express) {
app.get('/api/admin/tasks/available',
AuthenticationMWs.authenticate,
AuthenticationMWs.authorise(UserRoles.Admin),
AdminMWs.getAvailableTasks,
RenderingMWs.renderResult
);
app.get('/api/admin/tasks/scheduled/progress',
AuthenticationMWs.authenticate,
AuthenticationMWs.authorise(UserRoles.Admin),
AdminMWs.getTaskProgresses,
RenderingMWs.renderResult
);
app.post('/api/admin/tasks/scheduled/:id/start',
AuthenticationMWs.authenticate,
AuthenticationMWs.authorise(UserRoles.Admin),
AdminMWs.startTask,
RenderingMWs.renderResult
);
app.post('/api/admin/tasks/scheduled/:id/stop',
AuthenticationMWs.authenticate,
AuthenticationMWs.authorise(UserRoles.Admin),
AdminMWs.stopTask,
RenderingMWs.renderResult
);
}
}

View File

@ -1,63 +1,15 @@
import {AuthenticationMWs} from '../middlewares/user/AuthenticationMWs';
import {UserRoles} from '../../common/entities/UserDTO';
import {RenderingMWs} from '../middlewares/RenderingMWs';
import {AdminMWs} from '../middlewares/AdminMWs';
import {AuthenticationMWs} from '../../middlewares/user/AuthenticationMWs';
import {UserRoles} from '../../../common/entities/UserDTO';
import {RenderingMWs} from '../../middlewares/RenderingMWs';
import {Express} from 'express';
import {SettingsMWs} from '../../middlewares/admin/SettingsMWs';
export class AdminRouter {
export class SettingsRouter {
public static route(app: Express) {
this.addGetStatistic(app);
this.addGetDuplicates(app);
this.addTasks(app);
this.addSettings(app);
}
private static addGetStatistic(app: Express) {
app.get('/api/admin/statistic',
AuthenticationMWs.authenticate,
AuthenticationMWs.authorise(UserRoles.Admin),
AdminMWs.loadStatistic,
RenderingMWs.renderResult
);
}
private static addGetDuplicates(app: Express) {
app.get('/api/admin/duplicates',
AuthenticationMWs.authenticate,
AuthenticationMWs.authorise(UserRoles.Admin),
AdminMWs.getDuplicates,
RenderingMWs.renderResult
);
}
private static addTasks(app: Express) {
app.get('/api/admin/tasks/available',
AuthenticationMWs.authenticate,
AuthenticationMWs.authorise(UserRoles.Admin),
AdminMWs.getAvailableTasks,
RenderingMWs.renderResult
);
app.get('/api/admin/tasks/scheduled/progress',
AuthenticationMWs.authenticate,
AuthenticationMWs.authorise(UserRoles.Admin),
AdminMWs.getTaskProgresses,
RenderingMWs.renderResult
);
app.post('/api/admin/tasks/scheduled/:id/start',
AuthenticationMWs.authenticate,
AuthenticationMWs.authorise(UserRoles.Admin),
AdminMWs.startTask,
RenderingMWs.renderResult
);
app.post('/api/admin/tasks/scheduled/:id/stop',
AuthenticationMWs.authenticate,
AuthenticationMWs.authorise(UserRoles.Admin),
AdminMWs.stopTask,
RenderingMWs.renderResult
);
}
private static addSettings(app: Express) {
app.get('/api/settings',
AuthenticationMWs.authenticate,
@ -69,87 +21,87 @@ export class AdminRouter {
app.put('/api/settings/database',
AuthenticationMWs.authenticate,
AuthenticationMWs.authorise(UserRoles.Admin),
AdminMWs.updateDatabaseSettings,
SettingsMWs.updateDatabaseSettings,
RenderingMWs.renderOK
);
app.put('/api/settings/map',
AuthenticationMWs.authenticate,
AuthenticationMWs.authorise(UserRoles.Admin),
AdminMWs.updateMapSettings,
SettingsMWs.updateMapSettings,
RenderingMWs.renderOK
);
app.put('/api/settings/video',
AuthenticationMWs.authenticate,
AuthenticationMWs.authorise(UserRoles.Admin),
AdminMWs.updateVideoSettings,
SettingsMWs.updateVideoSettings,
RenderingMWs.renderOK
);
app.put('/api/settings/metafile',
AuthenticationMWs.authenticate,
AuthenticationMWs.authorise(UserRoles.Admin),
AdminMWs.updateMetaFileSettings,
SettingsMWs.updateMetaFileSettings,
RenderingMWs.renderOK
);
app.put('/api/settings/authentication',
AuthenticationMWs.authenticate,
AuthenticationMWs.authorise(UserRoles.Admin),
AdminMWs.updateAuthenticationSettings,
SettingsMWs.updateAuthenticationSettings,
RenderingMWs.renderOK
);
app.put('/api/settings/thumbnail',
AuthenticationMWs.authenticate,
AuthenticationMWs.authorise(UserRoles.Admin),
AdminMWs.updateThumbnailSettings,
SettingsMWs.updateThumbnailSettings,
RenderingMWs.renderOK
);
app.put('/api/settings/search',
AuthenticationMWs.authenticate,
AuthenticationMWs.authorise(UserRoles.Admin),
AdminMWs.updateSearchSettings,
SettingsMWs.updateSearchSettings,
RenderingMWs.renderOK
);
app.put('/api/settings/faces',
AuthenticationMWs.authenticate,
AuthenticationMWs.authorise(UserRoles.Admin),
AdminMWs.updateFacesSettings,
SettingsMWs.updateFacesSettings,
RenderingMWs.renderOK
);
app.put('/api/settings/share',
AuthenticationMWs.authenticate,
AuthenticationMWs.authorise(UserRoles.Admin),
AdminMWs.updateShareSettings,
SettingsMWs.updateShareSettings,
RenderingMWs.renderOK
);
app.put('/api/settings/randomPhoto',
AuthenticationMWs.authenticate,
AuthenticationMWs.authorise(UserRoles.Admin),
AdminMWs.updateRandomPhotoSettings,
SettingsMWs.updateRandomPhotoSettings,
RenderingMWs.renderOK
);
app.put('/api/settings/basic',
AuthenticationMWs.authenticate,
AuthenticationMWs.authorise(UserRoles.Admin),
AdminMWs.updateBasicSettings,
SettingsMWs.updateBasicSettings,
RenderingMWs.renderOK
);
app.put('/api/settings/other',
AuthenticationMWs.authenticate,
AuthenticationMWs.authorise(UserRoles.Admin),
AdminMWs.updateOtherSettings,
SettingsMWs.updateOtherSettings,
RenderingMWs.renderOK
);
app.put('/api/settings/indexing',
AuthenticationMWs.authenticate,
AuthenticationMWs.authorise(UserRoles.Admin),
AdminMWs.updateIndexingSettings,
SettingsMWs.updateIndexingSettings,
RenderingMWs.renderOK
);
app.put('/api/settings/tasks',
AuthenticationMWs.authenticate,
AuthenticationMWs.authorise(UserRoles.Admin),
AdminMWs.updateTasksSettings,
SettingsMWs.updateTasksSettings,
RenderingMWs.renderOK
);
}

View File

@ -5,24 +5,17 @@ import * as _http from 'http';
import {Server as HttpServer} from 'http';
// @ts-ignore
import * as locale from 'locale';
import {PublicRouter} from './routes/PublicRouter';
import {UserRouter} from './routes/UserRouter';
import {GalleryRouter} from './routes/GalleryRouter';
import {AdminRouter} from './routes/AdminRouter';
import {ErrorRouter} from './routes/ErrorRouter';
import {SharingRouter} from './routes/SharingRouter';
import {ObjectManagers} from './model/ObjectManagers';
import {Logger} from './Logger';
import {Config} from '../common/config/private/Config';
import {DatabaseType} from '../common/config/private/IPrivateConfig';
import {LoggerRouter} from './routes/LoggerRouter';
import {ThumbnailGeneratorMWs} from './middlewares/thumbnail/ThumbnailGeneratorMWs';
import {DiskManager} from './model/DiskManger';
import {NotificationRouter} from './routes/NotificationRouter';
import {ConfigDiagnostics} from './model/diagnostics/ConfigDiagnostics';
import {Localizations} from './model/Localizations';
import {CookieNames} from '../common/CookieNames';
import {PersonRouter} from './routes/PersonRouter';
import {Router} from './routes/Router';
import {ServerConfig} from '../common/config/private/IPrivateConfig';
const _session = require('cookie-session');
@ -82,22 +75,13 @@ export class Server {
Localizations.init();
this.app.use(locale(Config.Client.languages, 'en'));
if (Config.Server.Database.type !== DatabaseType.memory) {
if (Config.Server.Database.type !== ServerConfig.DatabaseType.memory) {
await ObjectManagers.InitSQLManagers();
} else {
await ObjectManagers.InitMemoryManagers();
}
PublicRouter.route(this.app);
UserRouter.route(this.app);
GalleryRouter.route(this.app);
PersonRouter.route(this.app);
SharingRouter.route(this.app);
AdminRouter.route(this.app);
NotificationRouter.route(this.app);
ErrorRouter.route(this.app);
Router.route(this.app);
// Get PORT from environment and store in Express.

View File

@ -1,6 +1,5 @@
import {SQLConnection} from '../backend/model/sql/SQLConnection';
import {Config} from '../common/config/private/Config';
import {DatabaseType, ReIndexingSensitivity} from '../common/config/private/IPrivateConfig';
import {ObjectManagers} from '../backend/model/ObjectManagers';
import {DiskMangerWorker} from '../backend/model/threading/DiskMangerWorker';
import {IndexingManager} from '../backend/model/sql/IndexingManager';
@ -10,6 +9,7 @@ import {SearchTypes} from '../common/entities/AutoCompleteItem';
import {Utils} from '../common/Utils';
import {GalleryManager} from '../backend/model/sql/GalleryManager';
import {DirectoryDTO} from '../common/entities/DirectoryDTO';
import {ServerConfig} from '../common/config/private/IPrivateConfig';
export interface BenchmarkResult {
duration: number;
@ -45,7 +45,7 @@ export class Benchmarks {
async bmListDirectory(): Promise<BenchmarkResult> {
const gm = new GalleryManager();
await this.setupDB();
Config.Server.Indexing.reIndexingSensitivity = ReIndexingSensitivity.low;
Config.Server.Indexing.reIndexingSensitivity = ServerConfig.ReIndexingSensitivity.low;
return await this.benchmark(() => gm.listDirectory('./'));
}
@ -122,7 +122,7 @@ export class Benchmarks {
if (fs.existsSync(this.dbPath)) {
fs.unlinkSync(this.dbPath);
}
Config.Server.Database.type = DatabaseType.sqlite;
Config.Server.Database.type = ServerConfig.DatabaseType.sqlite;
Config.Server.Database.sqlite.storage = this.dbPath;
await ObjectManagers.InitSQLManagers();
};

View File

@ -10,19 +10,29 @@ export const SupportedFormats = {
'mp4',
'webm',
'ogv',
'ogg',
'avi'
'ogg'
],
MetaFiles: [
'gpx'
],
TranscodeNeed: {
Photos: <string[]>[],
Videos: [
'avi',
'mkv',
'mov',
'wmv',
'flv'
],
},
WithDots: {
Photos: <string[]>[],
Videos: <string[]>[],
MetaFiles: <string[]>[],
}
};
SupportedFormats.Photos = SupportedFormats.Photos.concat(SupportedFormats.TranscodeNeed.Photos);
SupportedFormats.Videos = SupportedFormats.Videos.concat(SupportedFormats.TranscodeNeed.Videos);
SupportedFormats.WithDots.Photos = SupportedFormats.Photos.map(f => '.' + f);
SupportedFormats.WithDots.Videos = SupportedFormats.Videos.map(f => '.' + f);
SupportedFormats.WithDots.MetaFiles = SupportedFormats.MetaFiles.map(f => '.' + f);

View File

@ -1,114 +1,117 @@
import {ClientConfig} from '../public/ConfigClass';
import {TaskScheduleDTO} from '../../entities/task/TaskScheduleDTO';
export enum DatabaseType {
memory = 1, mysql = 2, sqlite = 3
}
export module ServerConfig {
export enum DatabaseType {
memory = 1, mysql = 2, sqlite = 3
}
export enum LogLevel {
error = 1, warn = 2, info = 3, verbose = 4, debug = 5, silly = 6
}
export enum LogLevel {
error = 1, warn = 2, info = 3, verbose = 4, debug = 5, silly = 6
}
export enum SQLLogLevel {
none = 1, error = 2, all = 3
}
export enum SQLLogLevel {
none = 1, error = 2, all = 3
}
export enum ThumbnailProcessingLib {
Jimp = 1,
gm = 2,
sharp = 3
}
export enum ThumbnailProcessingLib {
Jimp = 1,
gm = 2,
sharp = 3
}
export interface MySQLConfig {
host: string;
database: string;
username: string;
password: string;
}
export interface MySQLConfig {
host: string;
database: string;
username: string;
password: string;
}
export interface SQLiteConfig {
storage: string;
}
export interface SQLiteConfig {
storage: string;
}
export interface DataBaseConfig {
type: DatabaseType;
mysql?: MySQLConfig;
sqlite?: SQLiteConfig;
}
export interface DataBaseConfig {
type: DatabaseType;
mysql?: MySQLConfig;
sqlite?: SQLiteConfig;
}
export interface ThumbnailConfig {
folder: string;
processingLibrary: ThumbnailProcessingLib;
qualityPriority: boolean;
personFaceMargin: number; // in ration [0-1]
}
export interface ThumbnailConfig {
folder: string;
processingLibrary: ThumbnailProcessingLib;
qualityPriority: boolean;
personFaceMargin: number; // in ration [0-1]
}
export interface SharingConfig {
updateTimeout: number;
}
export interface SharingConfig {
updateTimeout: number;
}
export enum ReIndexingSensitivity {
low = 1, medium = 2, high = 3
}
export enum ReIndexingSensitivity {
low = 1, medium = 2, high = 3
}
export interface IndexingConfig {
folderPreviewSize: number;
cachedFolderTimeout: number; // Do not rescans the folder if seems ok
reIndexingSensitivity: ReIndexingSensitivity;
excludeFolderList: string[];
excludeFileList: string[];
}
export interface IndexingConfig {
folderPreviewSize: number;
cachedFolderTimeout: number; // Do not rescans the folder if seems ok
reIndexingSensitivity: ReIndexingSensitivity;
excludeFolderList: string[];
excludeFileList: string[];
}
export interface ThreadingConfig {
enable: boolean;
thumbnailThreads: number;
}
export interface ThreadingConfig {
enable: boolean;
thumbnailThreads: number;
}
export interface DuplicatesConfig {
listingLimit: number; // maximum number of duplicates to list
}
export interface DuplicatesConfig {
listingLimit: number; // maximum number of duplicates to list
}
export interface LogConfig {
level: LogLevel;
sqlLevel: SQLLogLevel;
}
export interface LogConfig {
level: LogLevel;
sqlLevel: SQLLogLevel;
}
export interface TaskConfig {
scheduled: TaskScheduleDTO[];
}
export interface TaskConfig {
scheduled: TaskScheduleDTO[];
}
export type codecType = 'libvpx-vp9' | 'libx264' | 'libvpx' | 'libx265';
export type resolutionType = 240 | 360 | 480 | 720 | 1080 | 1440 | 2160 | 4320;
export type formatType = 'mp4' | 'webm';
export type codecType = 'libvpx-vp9' | 'libx264' | 'libvpx' | 'libx265';
export type resolutionType = 240 | 360 | 480 | 720 | 1080 | 1440 | 2160 | 4320;
export type formatType = 'mp4' | 'webm';
export interface VideoConfig {
transcoding: {
bitRate: number,
resolution: resolutionType,
fps: number,
codec: codecType,
format: formatType
};
}
export interface VideoConfig {
transcoding: {
bitRate: number,
resolution: resolutionType,
fps: number,
codec: codecType,
format: formatType
};
}
export interface ServerConfig {
port: number;
host: string;
imagesFolder: string;
Thumbnail: ThumbnailConfig;
Threading: ThreadingConfig;
Database: DataBaseConfig;
Sharing: SharingConfig;
sessionTimeout: number;
Indexing: IndexingConfig;
photoMetadataSize: number;
Duplicates: DuplicatesConfig;
Log: LogConfig;
Tasks: TaskConfig;
Video: VideoConfig;
export interface Config {
port: number;
host: string;
imagesFolder: string;
Thumbnail: ThumbnailConfig;
Threading: ThreadingConfig;
Database: DataBaseConfig;
Sharing: SharingConfig;
sessionTimeout: number;
Indexing: IndexingConfig;
photoMetadataSize: number;
Duplicates: DuplicatesConfig;
Log: LogConfig;
Tasks: TaskConfig;
Video: VideoConfig;
}
}
export interface IPrivateConfig {
Server: ServerConfig;
Server: ServerConfig.Config;
Client: ClientConfig.Config;
}

View File

@ -1,41 +1,35 @@
import {PublicConfigClass} from '../public/ConfigClass';
import {
DatabaseType,
IPrivateConfig,
LogLevel,
ReIndexingSensitivity,
ServerConfig,
SQLLogLevel,
ThumbnailProcessingLib
} from './IPrivateConfig';
import {IPrivateConfig, ServerConfig,} from './IPrivateConfig';
import * as path from 'path';
import {ConfigLoader} from 'typeconfig';
import {Utils} from '../../Utils';
import {UserRoles} from '../../entities/UserDTO';
import {TaskTriggerType} from '../../entities/task/TaskScheduleDTO';
import {DefaultsTasks} from '../../entities/task/TaskDTO';
/**
* This configuration will be only at backend
*/
export class PrivateConfigClass extends PublicConfigClass implements IPrivateConfig {
public Server: ServerConfig = {
public Server: ServerConfig.Config = {
port: 80,
host: '0.0.0.0',
imagesFolder: 'demo/images',
Thumbnail: {
folder: 'demo/TEMP',
processingLibrary: ThumbnailProcessingLib.sharp,
processingLibrary: ServerConfig.ThumbnailProcessingLib.sharp,
qualityPriority: true,
personFaceMargin: 0.6
},
Log: {
level: LogLevel.info,
sqlLevel: SQLLogLevel.error
level: ServerConfig.LogLevel.info,
sqlLevel: ServerConfig.SQLLogLevel.error
},
sessionTimeout: 1000 * 60 * 60 * 24 * 7,
photoMetadataSize: 512 * 1024,
Database: {
type: DatabaseType.sqlite,
type: ServerConfig.DatabaseType.sqlite,
mysql: {
host: '',
username: '',
@ -57,7 +51,7 @@ export class PrivateConfigClass extends PublicConfigClass implements IPrivateCon
Indexing: {
folderPreviewSize: 2,
cachedFolderTimeout: 1000 * 60 * 60,
reIndexingSensitivity: ReIndexingSensitivity.low,
reIndexingSensitivity: ServerConfig.ReIndexingSensitivity.low,
excludeFolderList: [],
excludeFileList: []
},
@ -65,7 +59,19 @@ export class PrivateConfigClass extends PublicConfigClass implements IPrivateCon
listingLimit: 1000
},
Tasks: {
scheduled: []
scheduled: [{
taskName: DefaultsTasks[DefaultsTasks['Database Reset']],
config: {},
trigger: {type: TaskTriggerType.never}
}, {
taskName: DefaultsTasks[DefaultsTasks.Indexing],
config: {},
trigger: {type: TaskTriggerType.never}
}, {
taskName: DefaultsTasks[DefaultsTasks['Video Converting']],
config: {},
trigger: {type: TaskTriggerType.never}
}]
},
Video: {
transcoding: {
@ -79,9 +85,9 @@ export class PrivateConfigClass extends PublicConfigClass implements IPrivateCon
};
private ConfigLoader: any;
public setDatabaseType(type: DatabaseType) {
public setDatabaseType(type: ServerConfig.DatabaseType) {
this.Server.Database.type = type;
if (type === DatabaseType.memory) {
if (type === ServerConfig.DatabaseType.memory) {
this.Client.Search.enabled = false;
this.Client.Sharing.enabled = false;
}
@ -101,10 +107,10 @@ export class PrivateConfigClass extends PublicConfigClass implements IPrivateCon
if (Utils.enumToArray(UserRoles).map(r => r.key).indexOf(this.Client.unAuthenticatedUserRole) === -1) {
throw new Error('Unknown user role for Client.unAuthenticatedUserRole, found: ' + this.Client.unAuthenticatedUserRole);
}
if (Utils.enumToArray(LogLevel).map(r => r.key).indexOf(this.Server.Log.level) === -1) {
if (Utils.enumToArray(ServerConfig.LogLevel).map(r => r.key).indexOf(this.Server.Log.level) === -1) {
throw new Error('Unknown Server.log.level, found: ' + this.Server.Log.level);
}
if (Utils.enumToArray(SQLLogLevel).map(r => r.key).indexOf(this.Server.Log.sqlLevel) === -1) {
if (Utils.enumToArray(ServerConfig.SQLLogLevel).map(r => r.key).indexOf(this.Server.Log.sqlLevel) === -1) {
throw new Error('Unknown Server.log.level, found: ' + this.Server.Log.sqlLevel);
}

View File

@ -4,7 +4,7 @@ import {UserRoles} from '../../entities/UserDTO';
export module ClientConfig {
export enum MapProviders {
OpenStreetMap, Mapbox, Custom
OpenStreetMap = 0, Mapbox = 1, Custom = 2
}
export interface AutoCompleteConfig {

View File

@ -1,7 +1,7 @@
import {ClientConfig} from '../../config/public/ConfigClass';
import {ThreadingConfig} from '../../config/private/IPrivateConfig';
import {ServerConfig} from '../../config/private/IPrivateConfig';
export interface OtherConfigDTO {
Server: ThreadingConfig;
Server: ServerConfig.ThreadingConfig;
Client: ClientConfig.OtherConfig;
}

View File

@ -22,7 +22,6 @@ export interface PeriodicTaskTrigger extends TaskTrigger {
}
export interface TaskScheduleDTO {
priority: number;
taskName: string;
config: any;
trigger: NeverTaskTrigger | ScheduledTaskTrigger | PeriodicTaskTrigger;

View File

@ -47,7 +47,7 @@ import {TooltipModule} from 'ngx-bootstrap/tooltip';
import {BsDropdownModule} from 'ngx-bootstrap/dropdown';
import {CollapseModule} from 'ngx-bootstrap/collapse';
import {PopoverModule} from 'ngx-bootstrap/popover';
import {ThumbnailSettingsComponent} from './ui/settings/thumbnail/thumbanil.settings.component';
import {ThumbnailSettingsComponent} from './ui/settings/thumbnail/thumbnail.settings.component';
import {SearchSettingsComponent} from './ui/settings/search/search.settings.component';
import {SettingsService} from './ui/settings/settings.service';
import {ShareSettingsComponent} from './ui/settings/share/share.settings.component';

View File

@ -1,12 +1,12 @@
import {Component, OnInit} from '@angular/core';
import {AuthenticationService} from '../../../model/network/authentication.service';
import {DataBaseConfig, DatabaseType} from '../../../../../common/config/private/IPrivateConfig';
import {Utils} from '../../../../../common/Utils';
import {NotificationService} from '../../../model/notification.service';
import {NavigationService} from '../../../model/navigation.service';
import {SettingsComponent} from '../_abstract/abstract.settings.component';
import {DatabaseSettingsService} from './database.settings.service';
import {I18n} from '@ngx-translate/i18n-polyfill';
import {ServerConfig} from '../../../../../common/config/private/IPrivateConfig';
@Component({
selector: 'app-settings-database',
@ -15,7 +15,7 @@ import {I18n} from '@ngx-translate/i18n-polyfill';
'./../_abstract/abstract.settings.component.css'],
providers: [DatabaseSettingsService],
})
export class DatabaseSettingsComponent extends SettingsComponent<DataBaseConfig> implements OnInit {
export class DatabaseSettingsComponent extends SettingsComponent<ServerConfig.DataBaseConfig> implements OnInit {
public types: { key: number, value: string }[] = [];
public DatabaseType: any;
@ -30,8 +30,8 @@ export class DatabaseSettingsComponent extends SettingsComponent<DataBaseConfig>
ngOnInit() {
super.ngOnInit();
this.types = Utils.enumToArray(DatabaseType);
this.DatabaseType = DatabaseType;
this.types = Utils.enumToArray(ServerConfig.DatabaseType);
this.DatabaseType = ServerConfig.DatabaseType;
}

View File

@ -1,18 +1,18 @@
import {Injectable} from '@angular/core';
import {NetworkService} from '../../../model/network/network.service';
import {DataBaseConfig} from '../../../../../common/config/private/IPrivateConfig';
import {AbstractSettingsService} from '../_abstract/abstract.settings.service';
import {SettingsService} from '../settings.service';
import {ServerConfig} from '../../../../../common/config/private/IPrivateConfig';
@Injectable()
export class DatabaseSettingsService extends AbstractSettingsService<DataBaseConfig> {
export class DatabaseSettingsService extends AbstractSettingsService<ServerConfig.DataBaseConfig> {
constructor(private _networkService: NetworkService,
_settingsService: SettingsService) {
super(_settingsService);
}
public updateSettings(settings: DataBaseConfig): Promise<void> {
public updateSettings(settings: ServerConfig.DataBaseConfig): Promise<void> {
return this._networkService.putJson('/settings/database', {settings: settings});
}

View File

@ -1,9 +1,9 @@
import {Injectable} from '@angular/core';
import {NetworkService} from '../../../model/network/network.service';
import {DatabaseType} from '../../../../../common/config/private/IPrivateConfig';
import {ClientConfig} from '../../../../../common/config/public/ConfigClass';
import {SettingsService} from '../settings.service';
import {AbstractSettingsService} from '../_abstract/abstract.settings.service';
import {ServerConfig} from '../../../../../common/config/private/IPrivateConfig';
@Injectable()
export class FacesSettingsService extends AbstractSettingsService<ClientConfig.FacesConfig> {
@ -13,7 +13,7 @@ export class FacesSettingsService extends AbstractSettingsService<ClientConfig.F
}
public isSupported(): boolean {
return this._settingsService.settings.value.Server.Database.type !== DatabaseType.memory &&
return this._settingsService.settings.value.Server.Database.type !== ServerConfig.DatabaseType.memory &&
this._settingsService.settings.value.Client.Search.enabled === true;
}

View File

@ -4,12 +4,12 @@ import {AuthenticationService} from '../../../model/network/authentication.servi
import {NavigationService} from '../../../model/navigation.service';
import {NotificationService} from '../../../model/notification.service';
import {ErrorDTO} from '../../../../../common/entities/Error';
import {IndexingConfig, ReIndexingSensitivity} from '../../../../../common/config/private/IPrivateConfig';
import {SettingsComponent} from '../_abstract/abstract.settings.component';
import {Utils} from '../../../../../common/Utils';
import {I18n} from '@ngx-translate/i18n-polyfill';
import {ScheduledTasksService} from '../scheduled-tasks.service';
import {DefaultsTasks} from '../../../../../common/entities/task/TaskDTO';
import {ServerConfig} from '../../../../../common/config/private/IPrivateConfig';
@Component({
selector: 'app-settings-indexing',
@ -18,7 +18,7 @@ import {DefaultsTasks} from '../../../../../common/entities/task/TaskDTO';
'./../_abstract/abstract.settings.component.css'],
providers: [IndexingSettingsService],
})
export class IndexingSettingsComponent extends SettingsComponent<IndexingConfig, IndexingSettingsService>
export class IndexingSettingsComponent extends SettingsComponent<ServerConfig.IndexingConfig, IndexingSettingsService>
implements OnInit, OnDestroy {
@ -70,7 +70,7 @@ export class IndexingSettingsComponent extends SettingsComponent<IndexingConfig,
super.ngOnInit();
this.tasksService.subscribeToProgress();
this.types = Utils
.enumToArray(ReIndexingSensitivity);
.enumToArray(ServerConfig.ReIndexingSensitivity);
this.types.forEach(v => {
switch (v.value) {
case 'low':

View File

@ -2,14 +2,14 @@ import {Injectable} from '@angular/core';
import {NetworkService} from '../../../model/network/network.service';
import {SettingsService} from '../settings.service';
import {AbstractSettingsService} from '../_abstract/abstract.settings.service';
import {DatabaseType, IndexingConfig} from '../../../../../common/config/private/IPrivateConfig';
import {BehaviorSubject} from 'rxjs';
import {StatisticDTO} from '../../../../../common/entities/settings/StatisticDTO';
import {ScheduledTasksService} from '../scheduled-tasks.service';
import {DefaultsTasks} from '../../../../../common/entities/task/TaskDTO';
import {ServerConfig} from '../../../../../common/config/private/IPrivateConfig';
@Injectable()
export class IndexingSettingsService extends AbstractSettingsService<IndexingConfig> {
export class IndexingSettingsService extends AbstractSettingsService<ServerConfig.IndexingConfig> {
public statistic: BehaviorSubject<StatisticDTO>;
@ -35,13 +35,13 @@ export class IndexingSettingsService extends AbstractSettingsService<IndexingCon
});
}
public updateSettings(settings: IndexingConfig): Promise<void> {
public updateSettings(settings: ServerConfig.IndexingConfig): Promise<void> {
return this._networkService.putJson('/settings/indexing', {settings: settings});
}
public isSupported(): boolean {
return this._settingsService.settings.value.Server.Database.type !== DatabaseType.memory;
return this._settingsService.settings.value.Server.Database.type !== ServerConfig.DatabaseType.memory;
}

View File

@ -1,9 +1,9 @@
import {Injectable} from '@angular/core';
import {NetworkService} from '../../../model/network/network.service';
import {DatabaseType} from '../../../../../common/config/private/IPrivateConfig';
import {ClientConfig} from '../../../../../common/config/public/ConfigClass';
import {SettingsService} from '../settings.service';
import {AbstractSettingsService} from '../_abstract/abstract.settings.service';
import {ServerConfig} from '../../../../../common/config/private/IPrivateConfig';
@Injectable()
export class RandomPhotoSettingsService extends AbstractSettingsService<ClientConfig.SharingConfig> {
@ -19,7 +19,7 @@ export class RandomPhotoSettingsService extends AbstractSettingsService<ClientCo
}
public isSupported(): boolean {
return this._settingsService.settings.value.Server.Database.type !== DatabaseType.memory;
return this._settingsService.settings.value.Server.Database.type !== ServerConfig.DatabaseType.memory;
}
public updateSettings(settings: ClientConfig.SharingConfig): Promise<void> {

View File

@ -1,9 +1,9 @@
import {Injectable} from '@angular/core';
import {NetworkService} from '../../../model/network/network.service';
import {DatabaseType} from '../../../../../common/config/private/IPrivateConfig';
import {ClientConfig} from '../../../../../common/config/public/ConfigClass';
import {SettingsService} from '../settings.service';
import {AbstractSettingsService} from '../_abstract/abstract.settings.service';
import {ServerConfig} from '../../../../../common/config/private/IPrivateConfig';
@Injectable()
export class SearchSettingsService extends AbstractSettingsService<ClientConfig.SearchConfig> {
@ -13,7 +13,7 @@ export class SearchSettingsService extends AbstractSettingsService<ClientConfig.
}
public isSupported(): boolean {
return this._settingsService.settings.value.Server.Database.type !== DatabaseType.memory;
return this._settingsService.settings.value.Server.Database.type !== ServerConfig.DatabaseType.memory;
}
public updateSettings(settings: ClientConfig.SearchConfig): Promise<void> {

View File

@ -1,17 +1,10 @@
import {Injectable} from '@angular/core';
import {BehaviorSubject} from 'rxjs';
import {
DatabaseType,
IPrivateConfig,
LogLevel,
ReIndexingSensitivity,
SQLLogLevel,
ThumbnailProcessingLib
} from '../../../../common/config/private/IPrivateConfig';
import {NetworkService} from '../../model/network/network.service';
import {SortingMethods} from '../../../../common/entities/SortingMethods';
import {UserRoles} from '../../../../common/entities/UserDTO';
import {ClientConfig} from '../../../../common/config/public/ConfigClass';
import {IPrivateConfig, ServerConfig} from '../../../../common/config/private/IPrivateConfig';
@Injectable()
export class SettingsService {
@ -83,11 +76,11 @@ export class SettingsService {
},
Server: {
Database: {
type: DatabaseType.memory
type: ServerConfig.DatabaseType.memory
},
Log: {
level: LogLevel.info,
sqlLevel: SQLLogLevel.error
level: ServerConfig.LogLevel.info,
sqlLevel: ServerConfig.SQLLogLevel.error
},
Sharing: {
updateTimeout: 2000
@ -99,7 +92,7 @@ export class SettingsService {
personFaceMargin: 0.1,
folder: '',
qualityPriority: true,
processingLibrary: ThumbnailProcessingLib.sharp
processingLibrary: ServerConfig.ThumbnailProcessingLib.sharp
},
Threading: {
enable: true,
@ -109,7 +102,7 @@ export class SettingsService {
Indexing: {
cachedFolderTimeout: 0,
folderPreviewSize: 0,
reIndexingSensitivity: ReIndexingSensitivity.medium,
reIndexingSensitivity: ServerConfig.ReIndexingSensitivity.medium,
excludeFolderList: [],
excludeFileList: []
},
@ -134,7 +127,7 @@ export class SettingsService {
}
public async getSettings(): Promise<void> {
this.settings.next(await <Promise<IPrivateConfig>>this._networkService.getJson('/settings'));
this.settings.next(await this._networkService.getJson<Promise<IPrivateConfig>>('/settings'));
}

View File

@ -1,9 +1,9 @@
import {Injectable} from '@angular/core';
import {NetworkService} from '../../../model/network/network.service';
import {DatabaseType} from '../../../../../common/config/private/IPrivateConfig';
import {ClientConfig} from '../../../../../common/config/public/ConfigClass';
import {SettingsService} from '../settings.service';
import {AbstractSettingsService} from '../_abstract/abstract.settings.service';
import {ServerConfig} from '../../../../../common/config/private/IPrivateConfig';
@Injectable()
export class ShareSettingsService extends AbstractSettingsService<ClientConfig.SharingConfig> {
@ -15,7 +15,7 @@ export class ShareSettingsService extends AbstractSettingsService<ClientConfig.S
public isSupported(): boolean {
return this._settingsService.settings.value.Server.Database.type !== DatabaseType.memory &&
return this._settingsService.settings.value.Server.Database.type !== ServerConfig.DatabaseType.memory &&
this._settingsService.settings.value.Client.authenticationRequired === true;
}

View File

@ -3,7 +3,6 @@ import {TasksSettingsService} from './tasks.settings.service';
import {AuthenticationService} from '../../../model/network/authentication.service';
import {NavigationService} from '../../../model/navigation.service';
import {NotificationService} from '../../../model/notification.service';
import {TaskConfig} from '../../../../../common/config/private/IPrivateConfig';
import {SettingsComponent} from '../_abstract/abstract.settings.component';
import {I18n} from '@ngx-translate/i18n-polyfill';
import {ErrorDTO} from '../../../../../common/entities/Error';
@ -16,6 +15,7 @@ import {
TaskTriggerType
} from '../../../../../common/entities/task/TaskScheduleDTO';
import {Utils} from '../../../../../common/Utils';
import {ServerConfig} from '../../../../../common/config/private/IPrivateConfig';
@Component({
selector: 'app-settings-tasks',
@ -24,7 +24,7 @@ import {Utils} from '../../../../../common/Utils';
'./../_abstract/abstract.settings.component.css'],
providers: [TasksSettingsService]
})
export class TasksSettingsComponent extends SettingsComponent<TaskConfig, TasksSettingsService>
export class TasksSettingsComponent extends SettingsComponent<ServerConfig.TaskConfig, TasksSettingsService>
implements OnInit, OnDestroy, OnChanges {
disableButtons = false;
@ -152,7 +152,6 @@ export class TasksSettingsComponent extends SettingsComponent<TaskConfig, TasksS
this.settings.scheduled.push({
taskName: this._settingsService.availableTasks.value[0].Name,
config: {},
priority: 0,
trigger: {
type: TaskTriggerType.never
}

View File

@ -2,12 +2,12 @@ import {Injectable} from '@angular/core';
import {NetworkService} from '../../../model/network/network.service';
import {SettingsService} from '../settings.service';
import {AbstractSettingsService} from '../_abstract/abstract.settings.service';
import {TaskConfig} from '../../../../../common/config/private/IPrivateConfig';
import {BehaviorSubject} from 'rxjs';
import {TaskDTO} from '../../../../../common/entities/task/TaskDTO';
import {ServerConfig} from '../../../../../common/config/private/IPrivateConfig';
@Injectable()
export class TasksSettingsService extends AbstractSettingsService<TaskConfig> {
export class TasksSettingsService extends AbstractSettingsService<ServerConfig.TaskConfig> {
public availableTasks: BehaviorSubject<TaskDTO[]>;
@ -18,7 +18,7 @@ export class TasksSettingsService extends AbstractSettingsService<TaskConfig> {
this.availableTasks = new BehaviorSubject([]);
}
public updateSettings(settings: TaskConfig): Promise<void> {
public updateSettings(settings: ServerConfig.TaskConfig): Promise<void> {
return this._networkService.putJson('/settings/tasks', {settings: settings});
}

View File

@ -3,21 +3,21 @@ import {SettingsComponent} from '../_abstract/abstract.settings.component';
import {AuthenticationService} from '../../../model/network/authentication.service';
import {NavigationService} from '../../../model/navigation.service';
import {NotificationService} from '../../../model/notification.service';
import {ThumbnailConfig, ThumbnailProcessingLib} from '../../../../../common/config/private/IPrivateConfig';
import {ClientConfig} from '../../../../../common/config/public/ConfigClass';
import {ThumbnailSettingsService} from './thumbanil.settings.service';
import {ThumbnailSettingsService} from './thumbnail.settings.service';
import {Utils} from '../../../../../common/Utils';
import {I18n} from '@ngx-translate/i18n-polyfill';
import {ServerConfig} from '../../../../../common/config/private/IPrivateConfig';
@Component({
selector: 'app-settings-thumbnail',
templateUrl: './thumbanil.settings.component.html',
styleUrls: ['./thumbanil.settings.component.css',
templateUrl: './thumbnail.settings.component.html',
styleUrls: ['./thumbnail.settings.component.css',
'./../_abstract/abstract.settings.component.css'],
providers: [ThumbnailSettingsService],
})
export class ThumbnailSettingsComponent
extends SettingsComponent<{ server: ThumbnailConfig, client: ClientConfig.ThumbnailConfig }>
extends SettingsComponent<{ server: ServerConfig.ThumbnailConfig, client: ClientConfig.ThumbnailConfig }>
implements OnInit {
types: Array<any> = [];
ThumbnailProcessingLib: any;
@ -48,7 +48,7 @@ export class ThumbnailSettingsComponent
ngOnInit() {
super.ngOnInit();
this.types = Utils
.enumToArray(ThumbnailProcessingLib).map((v) => {
.enumToArray(ServerConfig.ThumbnailProcessingLib).map((v) => {
if (v.value.toLowerCase() === 'sharp') {
v.value += ' ' + this.i18n('(recommended)');
}
@ -57,7 +57,7 @@ export class ThumbnailSettingsComponent
}
return v;
});
this.ThumbnailProcessingLib = ThumbnailProcessingLib;
this.ThumbnailProcessingLib = ServerConfig.ThumbnailProcessingLib;
}
}

View File

@ -1,19 +1,20 @@
import {Injectable} from '@angular/core';
import {NetworkService} from '../../../model/network/network.service';
import {ClientConfig} from '../../../../../common/config/public/ConfigClass';
import {ThumbnailConfig} from '../../../../../common/config/private/IPrivateConfig';
import {AbstractSettingsService} from '../_abstract/abstract.settings.service';
import {SettingsService} from '../settings.service';
import {ServerConfig} from '../../../../../common/config/private/IPrivateConfig';
@Injectable()
export class ThumbnailSettingsService extends AbstractSettingsService<{ server: ThumbnailConfig, client: ClientConfig.ThumbnailConfig }> {
export class ThumbnailSettingsService
extends AbstractSettingsService<{ server: ServerConfig.ThumbnailConfig, client: ClientConfig.ThumbnailConfig }> {
constructor(private _networkService: NetworkService,
_settingsService: SettingsService) {
super(_settingsService);
}
public updateSettings(settings: { server: ThumbnailConfig, client: ClientConfig.ThumbnailConfig }): Promise<void> {
public updateSettings(settings: { server: ServerConfig.ThumbnailConfig, client: ClientConfig.ThumbnailConfig }): Promise<void> {
return this._networkService.putJson('/settings/thumbnail', {settings: settings});
}

View File

@ -15,7 +15,7 @@ export class UserManagerSettingsService {
}
public async getSettings(): Promise<boolean> {
return (await <Promise<IPrivateConfig>>this._networkService.getJson('/settings')).Client.authenticationRequired;
return (await this._networkService.getJson<Promise<IPrivateConfig>>('/settings')).Client.authenticationRequired;
}
public updateSettings(settings: boolean): Promise<void> {

View File

@ -28,7 +28,7 @@
<hr/>
<p class="title" i18n>Video transcoding:</p>
<div class="form-group row" [hidden]="simplifiedMode">
<div class="form-group row" [hidden]="simplifiedMode">
<label class="col-md-2 control-label" for="format" i18n>Format</label>
<div class="col-md-10">
<select id="format" class="form-control" [(ngModel)]="settings.server.transcoding.format"
@ -40,7 +40,7 @@
</div>
</div>
<div class="form-group row" [hidden]="simplifiedMode">
<div class="form-group row" [hidden]="simplifiedMode">
<label class="col-md-2 control-label" for="codec" i18n>Codec</label>
<div class="col-md-10">
<select id="codec" class="form-control" [(ngModel)]="settings.server.transcoding.codec"
@ -60,11 +60,12 @@
<option *ngFor="let resolution of resolutions" [ngValue]="resolution">{{resolution}}p
</option>
</select>
<small class="form-text text-muted" i18n>The height of the output video will be scaled down to this, while keeping the aspect ratio.</small>
<small class="form-text text-muted" i18n>The height of the output video will be scaled down to this, while
keeping the aspect ratio.</small>
</div>
</div>
<div class="form-group row" [hidden]="simplifiedMode">
<div class="form-group row" [hidden]="simplifiedMode">
<label class="col-md-2 control-label" for="fps" i18n>FPS</label>
<div class="col-md-10">
<select id="fps" class="form-control" [(ngModel)]="settings.server.transcoding.fps"
@ -73,24 +74,28 @@
<option *ngFor="let fps of fps" [ngValue]="fps">{{fps}}
</option>
</select>
<small class="form-text text-muted" i18n>Target frame per second (fps) of the output video will be scaled down this this.</small>
<small class="form-text text-muted" i18n>Target frame per second (fps) of the output video will be scaled down
this this.</small>
</div>
</div>
<div class="form-group row">
<label class="col-md-2 control-label" for="bitRate" i18n>Bit rate</label>
<div class="input-group col-md-10">
<input type="number" class="form-control" placeholder="2"
id="bitRate"
min="0"
step="0.1"
max="1000"
[(ngModel)]="bitRate"
name="bitRate" required>
<div class="input-group-append">
<span class="input-group-text">mbps</span>
<div class="col-md-10">
<div class="input-group">
<input type="number" class="form-control" placeholder="2"
id="bitRate"
min="0"
step="0.1"
max="1000"
[(ngModel)]="bitRate"
name="bitRate" required>
<div class="input-group-append">
<span class="input-group-text">mbps</span>
</div>
</div>
<small class="form-text text-muted" i18n>Target bit rate of the output video will be scaled down this this. This should be less than the
<small class="form-text text-muted" i18n>Target bit rate of the output video will be scaled down this this.
This should be less than the
upload rate of your home server.</small>
</div>
</div>
@ -136,7 +141,7 @@
<ng-container *ngIf="Progress != null">
<br/>
<hr/>
<span class="progress-details" i18n>indexing</span>: {{Progress.comment}} <br/>
<span class="progress-details" i18n>status</span>: {{Progress.comment}} <br/>
<span class="progress-details" i18n>elapsed</span>: {{tasksService.calcTimeElapsed(Progress) | duration}}<br/>
<span class="progress-details" i18n>left</span>: {{tasksService.calcTimeLeft(Progress) | duration}}
<div class="progress">

View File

@ -6,10 +6,10 @@ import {NavigationService} from '../../../model/navigation.service';
import {NotificationService} from '../../../model/notification.service';
import {ClientConfig} from '../../../../../common/config/public/ConfigClass';
import {I18n} from '@ngx-translate/i18n-polyfill';
import {codecType, formatType, resolutionType, VideoConfig} from '../../../../../common/config/private/IPrivateConfig';
import {ScheduledTasksService} from '../scheduled-tasks.service';
import {DefaultsTasks} from '../../../../../common/entities/task/TaskDTO';
import {ErrorDTO} from '../../../../../common/entities/Error';
import {ServerConfig} from '../../../../../common/config/private/IPrivateConfig';
@Component({
@ -19,11 +19,11 @@ import {ErrorDTO} from '../../../../../common/entities/Error';
'./../_abstract/abstract.settings.component.css'],
providers: [VideoSettingsService],
})
export class VideoSettingsComponent extends SettingsComponent<{ server: VideoConfig, client: ClientConfig.VideoConfig }> {
export class VideoSettingsComponent extends SettingsComponent<{ server: ServerConfig.VideoConfig, client: ClientConfig.VideoConfig }> {
resolutions: resolutionType[] = [360, 480, 720, 1080, 1440, 2160, 4320];
codecs: { [key: string]: codecType[] } = {webm: ['libvpx', 'libvpx-vp9'], mp4: ['libx264', 'libx265']};
formats: formatType[] = ['mp4', 'webm'];
resolutions: ServerConfig.resolutionType[] = [360, 480, 720, 1080, 1440, 2160, 4320];
codecs: { [key: string]: ServerConfig.codecType[] } = {webm: ['libvpx', 'libvpx-vp9'], mp4: ['libx264', 'libx265']};
formats: ServerConfig.formatType[] = ['mp4', 'webm'];
fps = [24, 25, 30, 48, 50, 60];
constructor(_authService: AuthenticationService,
@ -79,7 +79,7 @@ export class VideoSettingsComponent extends SettingsComponent<{ server: VideoCon
this.settings.server.transcoding.fps);
}
formatChanged(format: formatType) {
formatChanged(format: ServerConfig.formatType) {
this.settings.server.transcoding.codec = this.codecs[format][0];
}

View File

@ -1,8 +1,8 @@
import {Config} from '../../common/config/private/Config';
import {DatabaseType} from '../../common/config/private/IPrivateConfig';
import * as fs from 'fs';
import * as path from 'path';
import {SQLConnection} from '../../backend/model/sql/SQLConnection';
import {ServerConfig} from '../../common/config/private/IPrivateConfig';
declare let describe: any;
const savedDescribe = describe;
@ -17,7 +17,7 @@ export class SQLTestHelper {
tempDir: string;
dbPath: string;
constructor(public dbType: DatabaseType) {
constructor(public dbType: ServerConfig.DatabaseType) {
this.tempDir = path.join(__dirname, './tmp');
this.dbPath = path.join(__dirname, './tmp', 'test.db');
@ -26,13 +26,13 @@ export class SQLTestHelper {
static describe(name: string, tests: (helper?: SQLTestHelper) => void) {
savedDescribe(name, async () => {
if (SQLTestHelper.enable.sqlite) {
const helper = new SQLTestHelper(DatabaseType.sqlite);
const helper = new SQLTestHelper(ServerConfig.DatabaseType.sqlite);
savedDescribe('sqlite', () => {
return tests(helper);
});
}
if (SQLTestHelper.enable.mysql) {
const helper = new SQLTestHelper(DatabaseType.mysql);
const helper = new SQLTestHelper(ServerConfig.DatabaseType.mysql);
savedDescribe('mysql', function () {
this.timeout(99999999);
// @ts-ignore
@ -43,7 +43,7 @@ export class SQLTestHelper {
}
public async initDB() {
if (this.dbType === DatabaseType.sqlite) {
if (this.dbType === ServerConfig.DatabaseType.sqlite) {
await this.initSQLite();
} else {
await this.initMySQL();
@ -52,7 +52,7 @@ export class SQLTestHelper {
public async clearDB() {
if (this.dbType === DatabaseType.sqlite) {
if (this.dbType === ServerConfig.DatabaseType.sqlite) {
await this.clearUpSQLite();
} else {
await this.clearUpMysql();
@ -62,12 +62,12 @@ export class SQLTestHelper {
private async initSQLite() {
await this.resetSQLite();
Config.Server.Database.type = DatabaseType.sqlite;
Config.Server.Database.type = ServerConfig.DatabaseType.sqlite;
Config.Server.Database.sqlite.storage = this.dbPath;
}
private async initMySQL() {
Config.Server.Database.type = DatabaseType.mysql;
Config.Server.Database.type = ServerConfig.DatabaseType.mysql;
Config.Server.Database.mysql.database = 'pigallery2_test';
await this.resetMySQL();
@ -85,7 +85,7 @@ export class SQLTestHelper {
}
private async resetMySQL() {
Config.Server.Database.type = DatabaseType.mysql;
Config.Server.Database.type = ServerConfig.DatabaseType.mysql;
Config.Server.Database.mysql.database = 'pigallery2_test';
const conn = await SQLConnection.getConnection();
await conn.query('DROP DATABASE IF EXISTS ' + conn.options.database);
@ -94,7 +94,7 @@ export class SQLTestHelper {
}
private async clearUpMysql() {
Config.Server.Database.type = DatabaseType.mysql;
Config.Server.Database.type = ServerConfig.DatabaseType.mysql;
Config.Server.Database.mysql.database = 'pigallery2_test';
const conn = await SQLConnection.getConnection();
await conn.query('DROP DATABASE IF EXISTS ' + conn.options.database);

View File

@ -2,7 +2,6 @@ import {expect} from 'chai';
import * as fs from 'fs';
import * as path from 'path';
import {Config} from '../../../../../common/config/private/Config';
import {DatabaseType} from '../../../../../common/config/private/IPrivateConfig';
import {SQLConnection} from '../../../../../backend/model/sql/SQLConnection';
import {UserEntity} from '../../../../../backend/model/sql/enitites/UserEntity';
import {UserRoles} from '../../../../../common/entities/UserDTO';
@ -17,6 +16,7 @@ import {
} from '../../../../../backend/model/sql/enitites/PhotoEntity';
import {MediaDimensionEntity} from '../../../../../backend/model/sql/enitites/MediaEntity';
import {VersionEntity} from '../../../../../backend/model/sql/enitites/VersionEntity';
import {ServerConfig} from '../../../../../common/config/private/IPrivateConfig';
describe('Typeorm integration', () => {
@ -31,7 +31,7 @@ describe('Typeorm integration', () => {
fs.mkdirSync(tempDir);
}
Config.Server.Database.type = DatabaseType.sqlite;
Config.Server.Database.type = ServerConfig.DatabaseType.sqlite;
Config.Server.Database.sqlite.storage = dbPath;
};

View File

@ -1,7 +1,6 @@
import {expect} from 'chai';
import * as fs from 'fs';
import {Config} from '../../../../../common/config/private/Config';
import {ReIndexingSensitivity} from '../../../../../common/config/private/IPrivateConfig';
import {SQLConnection} from '../../../../../backend/model/sql/SQLConnection';
import {GalleryManager} from '../../../../../backend/model/sql/GalleryManager';
import {DirectoryDTO} from '../../../../../common/entities/DirectoryDTO';
@ -17,6 +16,7 @@ import {PersonManager} from '../../../../../backend/model/sql/PersonManager';
import {SQLTestHelper} from '../../../SQLTestHelper';
import {VersionManager} from '../../../../../backend/model/sql/VersionManager';
import {DiskMangerWorker} from '../../../../../backend/model/threading/DiskMangerWorker';
import {ServerConfig} from '../../../../../common/config/private/IPrivateConfig';
class GalleryManagerTest extends GalleryManager {
@ -457,7 +457,7 @@ describe('IndexingManager', (sqlHelper: SQLTestHelper) => {
});
it('with re indexing severity low', async () => {
Config.Server.Indexing.reIndexingSensitivity = ReIndexingSensitivity.low;
Config.Server.Indexing.reIndexingSensitivity = ServerConfig.ReIndexingSensitivity.low;
// @ts-ignore
fs.statSync = () => ({ctime: new Date(dirTime), mtime: new Date(dirTime)});