1
0
mirror of https://github.com/bpatrik/pigallery2.git synced 2024-11-24 08:42:24 +02:00

Project cleanup and version bumps

This commit is contained in:
Patrik J. Braun 2021-01-04 11:11:55 +01:00
parent 2f0d2a5e59
commit 5f0f09d420
20 changed files with 1124 additions and 2018 deletions

View File

@ -183,9 +183,7 @@
<li>prioritizes thumbnail generation (generating thumbnail first for the visible photos)</li>
<li>saving generated thumbnails to TEMP folder for reuse</li>
<li>supporting several core CPU</li>
<li>supporting hardware acceleration (<a href="https://github.com/lovell/sharp">sharp</a> and <a
href="https://github.com/aheckmann/gm">gm</a> as optional and JS-based <a
href="https://github.com/oliver-moran/jimp">Jimp</a> as fallback)
<li>supporting hardware acceleration (<a href="https://github.com/lovell/sharp">sharp</a>)
</li>
</ul>
</li>

View File

@ -62,7 +62,7 @@ const createDynamicTranslationFile = async (language: string) => {
translationXml.xliff.file[0].body[0]['trans-unit'] = filtered;
// save
const builder = new xml2js.Builder({trim: true, normalize: true});
const builder = new xml2js.Builder();
const xml = builder.buildObject(translationXml);
await fsp.writeFile(path.join(folder, `ts-only-msg.${language}.xlf`), xml);

2872
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -32,16 +32,16 @@
"dependencies": {
"body-parser": "1.19.0",
"cookie-parser": "1.4.5",
"cookie-session": "2.0.0-beta.3",
"cookie-session": "2.0.0-rc.1",
"csurf": "1.11.0",
"ejs": "3.1.5",
"bcrypt": "5.0.0",
"sharp": "0.23.4",
"exifreader": "3.12.2",
"exifreader": "3.13.0",
"express": "4.17.1",
"express-unless": "0.5.0",
"fluent-ffmpeg": "2.1.2",
"image-size": "0.9.1",
"image-size": "0.9.3",
"jimp": "0.16.1",
"locale": "0.1.0",
"reflect-metadata": "0.1.13",
@ -49,7 +49,7 @@
"ts-exif-parser": "0.2.1",
"ts-node-iptc": "1.0.11",
"typeconfig": "2.0.14",
"typeorm": "0.2.21",
"typeorm": "0.2.29",
"winston": "2.4.4"
},
"devDependencies": {
@ -70,32 +70,31 @@
"@ngx-translate/i18n-polyfill": "1.0.0",
"@types/bcrypt": "3.0.0",
"@types/bcryptjs": "2.4.2",
"@types/chai": "4.2.6",
"@types/chai": "4.2.14",
"@types/cookie-parser": "1.4.2",
"@types/cookie-session": "2.0.37",
"@types/csurf": "1.9.36",
"@types/ejs": "3.0.0",
"@types/express": "4.17.2",
"@types/express-jwt": "0.0.42",
"@types/fluent-ffmpeg": "2.1.11",
"@types/gulp": "4.0.6",
"@types/cookie-session": "2.0.42",
"@types/csurf": "1.11.0",
"@types/ejs": "3.0.5",
"@types/express": "4.17.9",
"@types/express-jwt": "6.0.0",
"@types/fluent-ffmpeg": "2.1.16",
"@types/gulp": "4.0.7",
"@types/gulp-zip": "4.0.1",
"@types/image-size": "0.8.0",
"@types/jasmine": "3.5.0",
"@types/jsonwebtoken": "8.3.5",
"@types/node": "12.12.14",
"@types/rimraf": "2.0.3",
"@types/sharp": "0.23.1",
"@types/jasmine": "3.6.2",
"@types/jsonwebtoken": "8.5.0",
"@types/node": "14.14.19",
"@types/sharp": "0.26.1",
"@types/winston": "2.4.4",
"@types/xml2js": "0.4.5",
"@types/xml2js": "0.4.7",
"@yaga/leaflet-ng2": "1.0.0",
"bootstrap": "4.4.1",
"bootstrap": "4.5.3",
"chai": "4.2.0",
"chai-http": "4.3.0",
"codelyzer": "5.2.0",
"core-js": "3.4.7",
"codelyzer": "6.0.1",
"core-js": "3.8.2",
"coveralls": "3.1.0",
"ejs-loader": "0.3.5",
"ejs-loader": "0.5.0",
"gulp": "4.0.2",
"gulp-json-editor": "2.5.4",
"gulp-typescript": "5.0.1",
@ -103,9 +102,9 @@
"hammerjs": "2.0.8",
"intl": "1.2.5",
"jasmine-core": "3.6.0",
"jasmine-spec-reporter": "5.0.2",
"jasmine-spec-reporter": "6.0.0",
"jw-bootstrap-switch-ng2": "2.0.5",
"karma": "4.4.1",
"karma": "5.2.3",
"karma-chrome-launcher": "3.1.0",
"karma-cli": "2.0.0",
"karma-coverage-istanbul-reporter": "3.0.3",
@ -113,7 +112,7 @@
"karma-jasmine-html-reporter": "1.5.4",
"karma-remap-istanbul": "0.6.0",
"karma-systemjs": "0.16.0",
"mocha": "8.1.3",
"mocha": "8.2.1",
"ng2-cookies": "1.0.12",
"ng2-slim-loading-bar": "4.0.0",
"ngx-bootstrap": "5.2.0",
@ -127,12 +126,12 @@
"rxjs-compat": "6.5.3",
"terser": "4.4.2",
"ts-helpers": "1.1.2",
"ts-node": "9.0.0",
"ts-node": "9.1.1",
"tslint": "6.1.3",
"typescript": "3.5.3",
"xlf-google-translate": "1.0.0-beta.19",
"xml2js": "0.4.23",
"zone.js": "0.10.2"
"zone.js": "0.11.3"
},
"//": [
"TODO: remove terser version lock once webpack is fixed",

View File

@ -36,8 +36,8 @@ export class GalleryMWs {
try {
const directory = await ObjectManagers.getInstance()
.GalleryManager.listDirectory(directoryName,
parseInt(req.query[QueryParams.gallery.knownLastModified], 10),
parseInt(req.query[QueryParams.gallery.knownLastScanned], 10));
parseInt(<string>req.query[QueryParams.gallery.knownLastModified], 10),
parseInt(<string>req.query[QueryParams.gallery.knownLastScanned], 10));
if (directory == null) {
req.resultPipe = new ContentWrapper(null, null, true);
@ -121,7 +121,7 @@ export class GalleryMWs {
try {
const query: RandomQuery = {};
if (req.query.directory) {
query.directory = DiskMangerWorker.normalizeDirPath(req.query.directory);
query.directory = DiskMangerWorker.normalizeDirPath(<string>req.query.directory);
}
if (req.query.recursive === 'true') {
query.recursive = true;
@ -136,10 +136,10 @@ export class GalleryMWs {
query.minResolution = parseFloat(req.query.minResolution.toString());
}
if (req.query.fromDate) {
query.fromDate = new Date(req.query.fromDate);
query.fromDate = new Date(<string>req.query.fromDate);
}
if (req.query.toDate) {
query.toDate = new Date(req.query.toDate);
query.toDate = new Date(<string>req.query.toDate);
}
if (query.minResolution && query.maxResolution && query.maxResolution < query.minResolution) {
return next(new ErrorDTO(ErrorCodes.INPUT_ERROR, 'Input error: min resolution is greater than the max resolution'));
@ -212,7 +212,7 @@ export class GalleryMWs {
let type: SearchTypes;
if (req.query[QueryParams.gallery.search.type]) {
type = parseInt(req.query[QueryParams.gallery.search.type], 10);
type = parseInt(<string>req.query[QueryParams.gallery.search.type], 10);
}
try {
const result = await ObjectManagers.getInstance().SearchManager.search(req.params.text, type);

View File

@ -307,20 +307,16 @@ export class SettingsMWs {
try {
const settings: {
photoProcessingLibrary: ServerConfig.PhotoProcessingLib,
server: ServerConfig.PhotoConfig,
client: ClientConfig.PhotoConfig
} = req.body.settings;
await ConfigDiagnostics.testThumbnailLib(settings.photoProcessingLibrary);
await ConfigDiagnostics.testServerPhotoConfig(settings.server);
await ConfigDiagnostics.testClientPhotoConfig(settings.client);
Config.Server.Media.photoProcessingLibrary = settings.photoProcessingLibrary;
Config.Server.Media.Photo = settings.server;
Config.Client.Media.Photo = settings.client;
// only updating explicitly set config (not saving config set by the diagnostics)
const original = await Config.original();
original.Server.Media.photoProcessingLibrary = settings.photoProcessingLibrary;
original.Server.Media.Photo = settings.server;
original.Client.Media.Photo = settings.client;
original.save();

View File

@ -100,7 +100,7 @@ export class AuthenticationMWs {
try {
const password = (req.body ? req.body.password : null) || null;
const sharingKey: string = req.query[QueryParams.gallery.sharingKey_query] || req.params[QueryParams.gallery.sharingKey_params];
const sharingKey: string = <string>req.query[QueryParams.gallery.sharingKey_query] || <string>req.params[QueryParams.gallery.sharingKey_params];
const sharing = await ObjectManagers.getInstance().SharingManager.findOne({
sharingKey: sharingKey
});
@ -181,7 +181,7 @@ export class AuthenticationMWs {
private static async getSharingUser(req: Request) {
if (Config.Client.Sharing.enabled === true &&
(!!req.query[QueryParams.gallery.sharingKey_query] || !!req.params[QueryParams.gallery.sharingKey_params])) {
const sharingKey: string = req.query[QueryParams.gallery.sharingKey_query] || req.params[QueryParams.gallery.sharingKey_params];
const sharingKey: string = <string>req.query[QueryParams.gallery.sharingKey_query] || <string>req.params[QueryParams.gallery.sharingKey_params];
const sharing = await ObjectManagers.getInstance().SharingManager.findOne({
sharingKey: sharingKey
});

View File

@ -1,9 +1,4 @@
let bcrypt: any;
try {
bcrypt = require('bcrypt');
} catch (err) {
bcrypt = require('bcryptjs');
}
import * as bcrypt from 'bcrypt';
export class PasswordHelper {
public static cryptPassword(password: string): string {

View File

@ -13,7 +13,7 @@ const LOG_TAG = '[ConfigDiagnostics]';
export class ConfigDiagnostics {
static checkReadWritePermission(path: string) {
static checkReadWritePermission(path: string): Promise<void> {
return new Promise((resolve, reject) => {
// tslint:disable-next-line:no-bitwise
fs.access(path, fs.constants.R_OK | fs.constants.W_OK, (err) => {
@ -48,7 +48,7 @@ export class ConfigDiagnostics {
}
static testClientVideoConfig(videoConfig: ClientConfig.VideoConfig) {
static testClientVideoConfig(videoConfig: ClientConfig.VideoConfig): Promise<void> {
return new Promise((resolve, reject) => {
try {
if (videoConfig.enabled === true) {
@ -86,19 +86,12 @@ export class ConfigDiagnostics {
sharp();
}
static async testThumbnailLib(processingLibrary: ServerConfig.PhotoProcessingLib) {
switch (processingLibrary) {
case ServerConfig.PhotoProcessingLib.sharp:
await this.testSharp();
break;
}
}
static async testTempFolder(folder: string) {
await this.checkReadWritePermission(folder);
}
static testImageFolder(folder: string) {
static testImageFolder(folder: string): Promise<void> {
return new Promise((resolve, reject) => {
if (!fs.existsSync(folder)) {
reject('Images folder not exists: \'' + folder + '\'');
@ -220,22 +213,19 @@ export class ConfigDiagnostics {
}
}
if (Config.Server.Media.photoProcessingLibrary !== ServerConfig.PhotoProcessingLib.Jimp) {
try {
await ConfigDiagnostics.testThumbnailLib(Config.Server.Media.photoProcessingLibrary);
} catch (ex) {
const err: Error = ex;
NotificationManager.warning('Thumbnail hardware acceleration is not possible.' +
' \'' + ServerConfig.PhotoProcessingLib[Config.Server.Media.photoProcessingLibrary] + '\' 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.' +
' \'' + ServerConfig.PhotoProcessingLib[Config.Server.Media.photoProcessingLibrary] + '\' node module is not found.' +
' Falling back temporally to JS based thumbnail generation');
Config.Server.Media.photoProcessingLibrary = ServerConfig.PhotoProcessingLib.Jimp;
}
try {
await ConfigDiagnostics.testSharp();
} catch (ex) {
const err: Error = ex;
Logger.warn(LOG_TAG, '[Thumbnail hardware acceleration] module error: ', err.toString());
Logger.warn(LOG_TAG, 'Thumbnail hardware acceleration is not possible.' +
' \'sharp\' node module is not found.' +
' Falling back temporally to JS based thumbnail generation');
process.exit(1);
}
try {
await ConfigDiagnostics.testTempFolder(Config.Server.Media.tempFolder);
} catch (ex) {

View File

@ -34,13 +34,9 @@ export class PhotoProcessing {
Config.Client.Media.Thumbnail.concurrentThumbnailGenerations = 1;
}
if (Config.Server.Threading.enabled === true &&
Config.Server.Media.photoProcessingLibrary === ServerConfig.PhotoProcessingLib.Jimp) {
this.taskQue = new ThumbnailTH(Config.Client.Media.Thumbnail.concurrentThumbnailGenerations);
} else {
this.taskQue = new TaskExecuter(Config.Client.Media.Thumbnail.concurrentThumbnailGenerations,
(input => PhotoWorker.render(input, Config.Server.Media.photoProcessingLibrary)));
}
this.taskQue = new TaskExecuter(Config.Client.Media.Thumbnail.concurrentThumbnailGenerations,
(input => PhotoWorker.render(input)));
this.initDone = true;
}

View File

@ -2,17 +2,15 @@ import {Metadata, Sharp} from 'sharp';
import {Logger} from '../../Logger';
import {FfmpegCommand, FfprobeData} from 'fluent-ffmpeg';
import {FFmpegFactory} from '../FFmpegFactory';
import {ServerConfig} from '../../../common/config/private/PrivateConfig';
export class PhotoWorker {
private static imageRenderer: (input: RendererInput) => Promise<void> = null;
private static videoRenderer: (input: RendererInput) => Promise<void> = null;
private static rendererType: ServerConfig.PhotoProcessingLib = null;
public static render(input: RendererInput, renderer: ServerConfig.PhotoProcessingLib): Promise<void> {
public static render(input: RendererInput): Promise<void> {
if (input.type === ThumbnailSourceType.Photo) {
return this.renderFromImage(input, renderer);
return this.renderFromImage(input);
}
if (input.type === ThumbnailSourceType.Video) {
return this.renderFromVideo(input);
@ -20,10 +18,9 @@ export class PhotoWorker {
throw new Error('Unsupported media type to render thumbnail:' + input.type);
}
public static renderFromImage(input: RendererInput, renderer: ServerConfig.PhotoProcessingLib): Promise<void> {
if (PhotoWorker.rendererType !== renderer) {
PhotoWorker.imageRenderer = ImageRendererFactory.build(renderer);
PhotoWorker.rendererType = renderer;
public static renderFromImage(input: RendererInput): Promise<void> {
if (PhotoWorker.imageRenderer === null) {
PhotoWorker.imageRenderer = ImageRendererFactory.build();
}
return PhotoWorker.imageRenderer(input);
}
@ -118,68 +115,10 @@ export class VideoRendererFactory {
export class ImageRendererFactory {
public static build(renderer: ServerConfig.PhotoProcessingLib): (input: RendererInput) => Promise<void> {
switch (renderer) {
case ServerConfig.PhotoProcessingLib.Jimp:
return ImageRendererFactory.Jimp();
case ServerConfig.PhotoProcessingLib.sharp:
return ImageRendererFactory.Sharp();
}
throw new Error('unknown renderer');
public static build(): (input: RendererInput) => Promise<void> {
return ImageRendererFactory.Sharp();
}
public static Jimp() {
const Jimp = require('jimp');
return async (input: RendererInput): Promise<void> => {
// generate thumbnail
Logger.silly('[JimpThRenderer] rendering thumbnail:' + input.mediaPath);
const image = await Jimp.read(input.mediaPath);
/**
* newWidth * newHeight = size*size
* newHeight/newWidth = height/width
*
* newHeight = (height/width)*newWidth
* newWidth * newWidth = (size*size) / (height/width)
*
* @type {number}
*/
const ratio = image.bitmap.height / image.bitmap.width;
const algo = input.qualityPriority === true ? Jimp.RESIZE_BEZIER : Jimp.RESIZE_NEAREST_NEIGHBOR;
if (input.cut) {
image.crop(
input.cut.left,
input.cut.top,
input.cut.width,
input.cut.height
);
}
if (input.makeSquare === false) {
if (image.bitmap.width < image.bitmap.height) {
image.resize(Math.min(input.size, image.bitmap.width), Jimp.AUTO, algo);
} else {
image.resize(Jimp.AUTO, Math.min(image.size, image.bitmap.height), algo);
}
} else {
image.resize(input.size / Math.min(ratio, 1), Jimp.AUTO, algo);
image.crop(0, 0, input.size, input.size);
}
image.quality(60); // set JPEG quality
await new Promise((resolve, reject) => {
image.write(input.outPath, (err: Error | null) => { // save
if (err) {
return reject('[JimpThRenderer] ' + err.toString());
}
resolve();
});
});
};
}
public static Sharp() {
const sharp = require('sharp');
sharp.cache(false);

View File

@ -103,7 +103,6 @@ export class ThumbnailTH extends ThreadPool<void> implements ITaskExecuter<Rende
return super.executeTask(<ThumbnailTask>{
type: WorkerTaskTypes.thumbnail,
input: input,
renderer: Config.Server.Media.photoProcessingLibrary
});
}
}

View File

@ -22,7 +22,7 @@ export class Worker {
}
break;
case WorkerTaskTypes.thumbnail:
result = await PhotoWorker.render((<ThumbnailTask>task).input, (<ThumbnailTask>task).renderer);
result = await PhotoWorker.render((<ThumbnailTask>task).input);
break;
default:
throw new Error('Unknown worker task type');
@ -54,7 +54,6 @@ export interface DiskManagerTask extends WorkerTask {
export interface ThumbnailTask extends WorkerTask {
input: RendererInput;
renderer: ServerConfig.PhotoProcessingLib;
}
export module WorkerTask {

View File

@ -19,10 +19,6 @@ export module ServerConfig {
none = 1, error = 2, all = 3
}
export enum PhotoProcessingLib {
sharp = 3,
Jimp = 1
}
export enum ReIndexingSensitivity {
low = 1, medium = 2, high = 3
@ -308,8 +304,6 @@ export module ServerConfig {
folder: string = 'demo/images';
@ConfigProperty({description: 'Thumbnails, coverted photos, videos will be stored here (write permission required)'})
tempFolder: string = 'demo/tmp';
@ConfigProperty({type: ServerConfig.PhotoProcessingLib})
photoProcessingLibrary: PhotoProcessingLib = ServerConfig.PhotoProcessingLib.sharp;
@ConfigProperty()
Video: VideoConfig = new VideoConfig();
@ConfigProperty()

View File

@ -12,7 +12,7 @@
<app-settings-entry
name="Threading"
description="Runs directory scanning and thumbnail generation (only for Jimp) in a different thread."
description="Runs directory scanning in a different thread."
i18n-description i18n-name
[ngModel]="states.Server.enabled">
</app-settings-entry>

View File

@ -4,29 +4,7 @@
{{Name}}</h5>
<div class="card-body">
<div [hidden]="!error" class="alert alert-danger" role="alert"><strong>Error: </strong>{{error}}</div>
<div [hidden]="states.photoProcessingLibrary.value!=PhotoProcessingLib.Jimp"
class="alert alert-warning"
role="alert" i18n>It is highly recommended to use hardware accelerated (sharp or gm) lib for thumbnail
generation
</div>
<div [hidden]="simplifiedMode">
<app-settings-entry
name="Thumbnail generation library"
i18n-name
[ngModel]="states.photoProcessingLibrary"
[optionMap]="libTypesMap"
[simplifiedMode]="simplifiedMode"
required="true">
<small *ngIf="states.photoProcessingLibrary.value==PhotoProcessingLib.sharp"
class="form-text text-muted" i18n>Make sure that sharp node module is installed (npm install sharp).
</small>
</app-settings-entry>
<hr/>
</div>
<p class="title" i18n>Photo converting:</p>
<app-settings-entry

View File

@ -20,13 +20,11 @@ import {ClientConfig} from '../../../../../common/config/public/ClientConfig';
providers: [PhotoSettingsService],
})
export class PhotoSettingsComponent extends SettingsComponent<{
photoProcessingLibrary: ServerConfig.PhotoProcessingLib,
server: ServerConfig.PhotoConfig,
client: ClientConfig.PhotoConfig
}> {
readonly resolutionTypes = [720, 1080, 1440, 2160, 4320];
resolutions: { key: number, value: string }[] = [];
PhotoProcessingLib = ServerConfig.PhotoProcessingLib;
JobProgressStates = JobProgressStates;
readonly jobName = DefaultsJobs[DefaultsJobs['Photo Converting']];
@ -38,7 +36,6 @@ export class PhotoSettingsComponent extends SettingsComponent<{
notification: NotificationService,
i18n: I18n) {
super(i18n('Photo'), _authService, _navigation, _settingsService, notification, i18n, s => ({
photoProcessingLibrary: s.Server.Media.photoProcessingLibrary,
client: s.Client.Media.Photo,
server: s.Server.Media.Photo
}));

View File

@ -7,7 +7,6 @@ import {ClientConfig} from '../../../../../common/config/public/ClientConfig';
@Injectable()
export class PhotoSettingsService extends AbstractSettingsService<{
photoProcessingLibrary: ServerConfig.PhotoProcessingLib,
server: ServerConfig.PhotoConfig,
client: ClientConfig.PhotoConfig
}> {
@ -18,7 +17,6 @@ export class PhotoSettingsService extends AbstractSettingsService<{
public updateSettings(settings: {
photoProcessingLibrary: ServerConfig.PhotoProcessingLib,
server: ServerConfig.PhotoConfig,
client: ClientConfig.PhotoConfig
}): Promise<void> {

View File

@ -9,7 +9,7 @@
<app-settings-entry
name="Thumbnail Quality"
description="High quality may be slow. Especially with Jimp."
description="High quality may be slow."
i18n-description i18n-name
[ngModel]="states.server.qualityPriority"
[simplifiedMode]="simplifiedMode">

View File

@ -29,7 +29,7 @@ describe('Authentication middleware', () => {
query: {},
params: {}
};
const next = (err: ErrorDTO) => {
const next: any = (err: ErrorDTO) => {
expect(err).to.be.undefined;
done();
};
@ -45,7 +45,7 @@ describe('Authentication middleware', () => {
params: {}
};
Config.Client.authenticationRequired = true;
const next = (err: ErrorDTO) => {
const next: any = (err: ErrorDTO) => {
expect(err).not.to.be.undefined;
expect(err.code).to.be.eql(ErrorCodes.NOT_AUTHENTICATED);
done();
@ -136,7 +136,7 @@ describe('Authentication middleware', () => {
},
sessionOptions: {},
};
const next = (err: ErrorDTO) => {
const next: any = (err: ErrorDTO) => {
expect(err).not.to.be.undefined;
expect(err.code).to.be.eql(ErrorCodes.ALREADY_AUTHENTICATED);
done();
@ -156,7 +156,7 @@ describe('Authentication middleware', () => {
},
sessionOptions: {}
};
const next = (err: ErrorDTO) => {
const next: any = (err: ErrorDTO) => {
expect(err).to.be.undefined;
done();
};
@ -173,7 +173,7 @@ describe('Authentication middleware', () => {
},
sessionOptions: {}
};
const next = (err: ErrorDTO) => {
const next: any = (err: ErrorDTO) => {
expect(err).not.to.be.undefined;
expect(err.code).to.be.eql(ErrorCodes.NOT_AUTHORISED);
done();
@ -194,7 +194,7 @@ describe('Authentication middleware', () => {
query: {},
params: {}
};
const next = (err: ErrorDTO) => {
const next: any = (err: ErrorDTO) => {
expect(err).not.to.be.undefined;
expect(err.code).to.be.eql(ErrorCodes.INPUT_ERROR);
done();
@ -209,7 +209,7 @@ describe('Authentication middleware', () => {
query: {},
params: {}
};
const next = (err: ErrorDTO) => {
const next: any = (err: ErrorDTO) => {
expect(err).not.to.be.undefined;
expect(err.code).to.be.eql(ErrorCodes.INPUT_ERROR);
done();
@ -226,7 +226,7 @@ describe('Authentication middleware', () => {
query: {},
params: {}
};
const next = (err: ErrorDTO) => {
const next: any = (err: ErrorDTO) => {
expect(err).not.to.be.undefined;
expect(err.code).to.be.eql(ErrorCodes.INPUT_ERROR);
done();
@ -248,7 +248,7 @@ describe('Authentication middleware', () => {
query: {},
params: {}
};
const next = (err: ErrorDTO) => {
const next: any = (err: ErrorDTO) => {
expect(err).not.to.be.undefined;
expect(err.code).to.be.eql(ErrorCodes.CREDENTIAL_NOT_FOUND);
done();
@ -275,7 +275,7 @@ describe('Authentication middleware', () => {
query: {},
params: {}
};
const next = (err: ErrorDTO) => {
const next: any = (err: ErrorDTO) => {
expect(err).to.be.undefined;
expect(req.session.user).to.be.eql('test user');
done();